从 Activity 的 Fragment 的数组列表中删除项目
Delete item from arraylist on Fragment from Activity
我正在尝试通过创建一个可以删除项目的简单杂货清单来学习如何在具有活动的片段之间来回传递数据。杂货 ArrayList 将与删除按钮一起位于 Activity 中,片段将显示 ArrayList。当应用程序启动并加载所有内容时,用户将能够 select Fragment 列表中的项目。当用户点击 Delete 时,ArrayList 中的 selected 项将被删除,Fragment 将重新加载更新后的列表。
我可以启动应用程序并且一切正常加载,直到我删除一个项目。该项目删除(我有一个日志要检查)但我需要找到一种方法来更新片段中的 ArrayList。当我再次尝试删除另一个项目时,应用程序崩溃了。
这是我的 logcat:
java.lang.IllegalStateException: The content of the adapter has
changed but ListView did not receive a notification. Make sure
the content of your adapter is not modified from a background
thread, but only from the UI thread. Make sure your adapter calls
notifyDataSetChanged() when its content changes. [in ListView(2131427424,
class android.widget.ListView) with Adapter(class android.widget.ArrayAdapter)]
这是我的主菜Activity:
public class MainActivity extends AppCompatActivity implements Tab1.OnDataPass {
public SectionsPageAdapater mSectionsPageAdapter;
ViewPager mViewPager;
ArrayList<String> valuesArray = new ArrayList<String>();
int index = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPageAdapter = new SectionsPageAdapater(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.viewContainer);
valuesArray.add("apple");
valuesArray.add("banana");
valuesArray.add("cherry");
valuesArray.add("dragon fruit");
valuesArray.add("eggplant");
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
setupViewPager(mViewPager);
}
@Override
public void onDataPass(Integer indexNum) {
index = indexNum;
}
public void onClickDelete (View v) {
if (index >= 0) {
valuesArray.remove(index);
}
index = -1;
}
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapater adapter = new SectionsPageAdapater(getSupportFragmentManager());
adapter.addFragment(new Tab1(), "TAB1");
viewPager.setAdapter(adapter);
}
public ArrayList<String> getDataLog() {
return valuesArray;
}
}
我的片段:
public class Tab1 extends Fragment {
Button btnPass, btnPass2;
ListView listview;
ArrayList<String> valuesArray = new ArrayList<String>();
int index = -1;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_tab1,container,false);
btnPass = view.findViewById(R.id.btnPass);
btnPass2 = view.findViewById(R.id.btnPass2);
listview = view.findViewById (R.id.listview);
MainActivity activity = (MainActivity) getActivity();
valuesArray = activity.getDataLog();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_list_item_1, valuesArray);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
index = (int) id;
passData((index));
}
});
return view;
}
OnDataPass dataPasser;
public interface OnDataPass {
void onDataPass(Integer index);
}
@Override
public void onAttach(Context a) {
super.onAttach(a);
dataPasser = (OnDataPass) a;
}
public void passData(Integer index) {
dataPasser.onDataPass(index);
}
}
我的适配器:
public class SectionsPageAdapater extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public SectionsPageAdapater(FragmentManager fm) {
super(fm);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
}
在Android中,每一个ListView
对象都有一个对应的Adapter
对象,该对象实际持有数据,并将View
传递给ListView
以显示它。需要注意的是,每次数据、适配器保持更改时,您必须显式调用适配器的 notifyDatasetChanged
方法 以确保您的 ListView
对象是通知更改并处理相应的 UI 更新。
因此,在您的情况下,您应该将 ArrayAdapter
对象存储在 Activity class 中,并将其传递给您的 Fragment 而不是保存数据的实际 ArrayList。每当用户按下删除按钮时,都会调用 onClickDelete
方法。在该方法中,在改变实际的 ArrayList 之后,您应该调用适配器的 notifyDatasetChanged
方法。
设置您的 Fragment
/Activity
关系,这样:
当您调用 passData
时,您传递的是 position
而不是 id
值:.
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
passData(position);
}
/* Activity */
@Override
public void onDataPass(int index) {
this.indexToDelete = index;
}
当您调用 onClickDelete
时,删除该元素并在您的 ListView
的适配器上调用 notifyDataSetChanged()
。为此,您需要引用您的 Fragment
(如果使用 ViewPager,这比通常情况下有点棘手),或者您需要使用一些替代机制,如 EventBus。在这里,您可以只存储对 Tab1
:
的引用
//Instance variable
Tab1 tab1;
//...
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapater adapter = new SectionsPageAdapater(getSupportFragmentManager());
tab1 = new Tab1();
adapter.addFragment(tab1, "TAB1");
viewPager.setAdapter(adapter);
}
然后...
public void onClickDelete (View v) {
if(indexToDelete < 0 || indexToDelete >= valuesArray.size()) {
return; //invalid index
}
valuesArray.remove(indexToDelete);
tab1.listView.getAdapter().notifyDataSetChanged();
}
我正在尝试通过创建一个可以删除项目的简单杂货清单来学习如何在具有活动的片段之间来回传递数据。杂货 ArrayList 将与删除按钮一起位于 Activity 中,片段将显示 ArrayList。当应用程序启动并加载所有内容时,用户将能够 select Fragment 列表中的项目。当用户点击 Delete 时,ArrayList 中的 selected 项将被删除,Fragment 将重新加载更新后的列表。
我可以启动应用程序并且一切正常加载,直到我删除一个项目。该项目删除(我有一个日志要检查)但我需要找到一种方法来更新片段中的 ArrayList。当我再次尝试删除另一个项目时,应用程序崩溃了。
这是我的 logcat:
java.lang.IllegalStateException: The content of the adapter has
changed but ListView did not receive a notification. Make sure
the content of your adapter is not modified from a background
thread, but only from the UI thread. Make sure your adapter calls
notifyDataSetChanged() when its content changes. [in ListView(2131427424,
class android.widget.ListView) with Adapter(class android.widget.ArrayAdapter)]
这是我的主菜Activity:
public class MainActivity extends AppCompatActivity implements Tab1.OnDataPass {
public SectionsPageAdapater mSectionsPageAdapter;
ViewPager mViewPager;
ArrayList<String> valuesArray = new ArrayList<String>();
int index = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPageAdapter = new SectionsPageAdapater(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.viewContainer);
valuesArray.add("apple");
valuesArray.add("banana");
valuesArray.add("cherry");
valuesArray.add("dragon fruit");
valuesArray.add("eggplant");
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
setupViewPager(mViewPager);
}
@Override
public void onDataPass(Integer indexNum) {
index = indexNum;
}
public void onClickDelete (View v) {
if (index >= 0) {
valuesArray.remove(index);
}
index = -1;
}
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapater adapter = new SectionsPageAdapater(getSupportFragmentManager());
adapter.addFragment(new Tab1(), "TAB1");
viewPager.setAdapter(adapter);
}
public ArrayList<String> getDataLog() {
return valuesArray;
}
}
我的片段:
public class Tab1 extends Fragment {
Button btnPass, btnPass2;
ListView listview;
ArrayList<String> valuesArray = new ArrayList<String>();
int index = -1;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_tab1,container,false);
btnPass = view.findViewById(R.id.btnPass);
btnPass2 = view.findViewById(R.id.btnPass2);
listview = view.findViewById (R.id.listview);
MainActivity activity = (MainActivity) getActivity();
valuesArray = activity.getDataLog();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_list_item_1, valuesArray);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
index = (int) id;
passData((index));
}
});
return view;
}
OnDataPass dataPasser;
public interface OnDataPass {
void onDataPass(Integer index);
}
@Override
public void onAttach(Context a) {
super.onAttach(a);
dataPasser = (OnDataPass) a;
}
public void passData(Integer index) {
dataPasser.onDataPass(index);
}
}
我的适配器:
public class SectionsPageAdapater extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public SectionsPageAdapater(FragmentManager fm) {
super(fm);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
}
在Android中,每一个ListView
对象都有一个对应的Adapter
对象,该对象实际持有数据,并将View
传递给ListView
以显示它。需要注意的是,每次数据、适配器保持更改时,您必须显式调用适配器的 notifyDatasetChanged
方法 以确保您的 ListView
对象是通知更改并处理相应的 UI 更新。
因此,在您的情况下,您应该将 ArrayAdapter
对象存储在 Activity class 中,并将其传递给您的 Fragment 而不是保存数据的实际 ArrayList。每当用户按下删除按钮时,都会调用 onClickDelete
方法。在该方法中,在改变实际的 ArrayList 之后,您应该调用适配器的 notifyDatasetChanged
方法。
设置您的 Fragment
/Activity
关系,这样:
当您调用
passData
时,您传递的是position
而不是id
值:.public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { passData(position); } /* Activity */ @Override public void onDataPass(int index) { this.indexToDelete = index; }
当您调用
的引用onClickDelete
时,删除该元素并在您的ListView
的适配器上调用notifyDataSetChanged()
。为此,您需要引用您的Fragment
(如果使用 ViewPager,这比通常情况下有点棘手),或者您需要使用一些替代机制,如 EventBus。在这里,您可以只存储对Tab1
://Instance variable Tab1 tab1; //... private void setupViewPager(ViewPager viewPager) { SectionsPageAdapater adapter = new SectionsPageAdapater(getSupportFragmentManager()); tab1 = new Tab1(); adapter.addFragment(tab1, "TAB1"); viewPager.setAdapter(adapter); }
然后...
public void onClickDelete (View v) {
if(indexToDelete < 0 || indexToDelete >= valuesArray.size()) {
return; //invalid index
}
valuesArray.remove(indexToDelete);
tab1.listView.getAdapter().notifyDataSetChanged();
}