java - 当我向arraylist添加值以将内容添加到listview时,android ram不断上升
问题描述
我在位于活动内的 3 个片段之一中有一个列表视图。
我的代码的工作方式:活动内的按钮调用 pageAdapter 内的函数。然后适配器函数调用片段内部的函数来添加值并使用 notifyDataSetInvalidated() 刷新列表视图;
我的目标:当我在活动中按下按钮时,pageAdapter 函数会将内容添加到列表视图。然后将此内容放置在片段中。
我的问题:一切似乎都像我编程的那样工作。但是,当我查看 android profiler 时,这个应用程序似乎占用了大量内存。每次我单击按钮时,内存/内存都会不断增加 1 mb。此外,每次我添加一个值时,RAM 都会增加 40-100 mb 并且不会减少。
为什么会这样?这是正常的吗?这是内存泄漏吗?我该如何解决这个问题?我有更好的方法来引用片段吗?
这是 MainActivity 的代码
public class MainActivity extends AppCompatActivity implements listFragment.OnFragmentInteractionListener,list2Fragment.OnFragmentInteractionListener,list3Fragment.OnFragmentInteractionListener {
private TabLayout tabLayout;
private Button micBtn;
private ImageButton camBtn;
private TextView resultText;
PagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// instantiate the textview and button
resultText = (TextView)findViewById(R.id.micText);
// mic button
micBtn = (Button)findViewById(R.id.micBtn);
//toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
camBtn = (ImageButton) findViewById(R.id.menubar);
camBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent Intent = new Intent(MainActivity.this,CameraActivity.class);
startActivity(Intent);
}
});
// end of toolbar code
// tablayout
tabLayout = (TabLayout)findViewById(R.id.tablayout);
tabLayout.addTab(tabLayout.newTab().setText("list2"));
tabLayout.addTab(tabLayout.newTab().setText("list"));
tabLayout.addTab(tabLayout.newTab().setText("list3"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager)findViewById(R.id.mainviewpager);
adapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.setOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener( tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
System.out.print("this is the "+tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
// end of tablayout code
}
public void ontest(View v){
adapter.addList();
}
public void onButtonClick(View v){
if(v.getId() == R.id.micBtn){
promptSpeechInput();
}
}
public void promptSpeechInput(){
Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, Locale.getDefault());
i.putExtra(RecognizerIntent.EXTRA_PROMPT,"say something");
try {
startActivityForResult(i, 100);
}catch(ActivityNotFoundException a){
Toast.makeText(MainActivity.this,"sorry your device does not support speech to text ",Toast.LENGTH_LONG).show();
}
}
public void onActivityResult(int request_code,int result_code,Intent i){
super.onActivityResult(request_code,result_code,i);
switch (request_code)
{
case 100: if(result_code == RESULT_OK && i != null){
ArrayList<String> result = i.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
resultText.setText(result.get(0));
}
break;
}
}
@Override
public void onFragmentInteraction(Uri uri) {
Toast.makeText(getBaseContext(),"4324",Toast.LENGTH_LONG).show();
}
}
这是 pageAdapter 的代码
public class PagerAdapter extends FragmentStatePagerAdapter {
int mNoOfTabs;
listFragment CF;
public PagerAdapter(FragmentManager fm, int NumberOfTabs){
super(fm);
this.mNoOfTabs = NumberOfTabs;
}
@Override
public Fragment getItem(int position) {
switch (position){
case 0:
list2Fragment NF = new list2Fragment();
return NF;
case 1:
CF = new listFragment();
return CF;
case 2:
list3Fragment TF = new list3Fragment();
return TF;
default:
return null;
}
}
@Override
public int getCount() {
return mNoOfTabs;
}
public void addList(){
CF.addlist();
}
}
这是片段的代码
public class listFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
// array s
int[] counter = {2,23,41,2,2};
public ArrayList<String> mylist = new ArrayList<String>();
listAdapter listAdapter;
public listFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment tab1.
*/
// TODO: Rename and change types and number of parameters
public static listFragment newInstance(String param1, String param2) {
listFragment fragment = new listFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mylist.add("hello");
mylist.add("nice");
mylist.add("cool");
mylist.add("gaming");
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_list, container, false);
ListView listView = (ListView)rootView.findViewById(R.id.listListView);
listAdapter = new listAdapter();
listView.setAdapter(listAdapter);
return rootView;
}
public class listAdapter extends BaseAdapter {
@Override
public int getCount() {
return mylist.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.adapter_list,null);
TextView textView = (TextView)convertView.findViewById(R.id.textView);
textView.setText(mylist.get(position));
return convertView;
}
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
public OnFragmentInteractionListener getmListener() {
return mListener;
}
public void addlist(){
Toast.makeText(getContext(),"i am clicked",Toast.LENGTH_LONG).show();
mylist.add("hello");
listAdapter.notifyDataSetInvalidated();
}
}
解决方案
为什么会这样?正常吗?
这是正常的。考虑一下 - 每次您向数组列表添加内容时,您的应用程序都需要将该数据存储在某处。由于您没有将列表写入磁盘以进行持久性长期存储,因此它存储在 RAM 中以供程序的运行实例使用。
这是内存泄漏吗?我该如何解决这个问题?
通常,只要存在潜在的内存泄漏,大多数 IDE 都会发出警告。但是在这种情况下,您添加到数组列表中的任何内容似乎都会在以后不断被引用 - 所以如果我的理解是正确的,那不是内存泄漏。仅当您拥有不再引用但垃圾收集器无法收集的对象时才会发生这种情况。
至于解决内存问题,您总是可以尝试不同的方法。就像我之前暗示的那样,如果您的列表将在多次运行中持续存在,我建议将该输出存储到外部列表并在需要时调用它。如果不再需要它们,另一种选择是从数组列表中删除对象。如果不了解您需要列表的全部范围,真的很难说。
活动是否有更好的方式与片段进行通信?
如果您想要其他选项,此链接可能包含您正在寻找的一些内容
推荐阅读
- javascript - 如何通过解构赋值将数据绑定到这个?
- google-apps-script - 使用 Apps 脚本将公式插入 Google 表格列
- mvvm - 如何将视图模型中的单个变量绑定到视图
- c# - 一旦玩家离开对撞机门区域,我如何触发一些动作?
- c# - EF 包含列表始终为空
- azure - Azure Function V2 异常日志缺少堆栈跟踪
- python - 使用“OR”组合多个 Selenium 等待?
- android - 三星 S8 上的导航栏可见性
- css - Vue.js vuetify CSS3 无法将 span 元素与按钮中间垂直对齐
- css - 使背景颜色的底部边缘另一种颜色