目标:我有一个活动,在两个片段中。 ideia用于传递两个片段,选择一个类别并更新其项目列表。在活动加载时,默认情况下会定义一个类别。
问题:在活动加载时,ItemsFragment不显示/更新itemsLisView。此外,ItemAdapter的getView方法仅被调用两次,即使该列表有五个项目。
事实:
if (getArguments() != null)
的原因。在我获得Null指针异常之前。 研究:关于这两个主题存在很多问题。
这些是我经历过的一些链接示例(成千上万),试图为我的案例找到解决方案。不幸的是,他们都没有工作。
我已经在这个问题上待了将近5天了,我想我在这里错过了一些Android概念。它与Java编程无关,或者至少我希望如此。
问题:
如需了解更多信息,请不要随意询问。 提前感谢您的帮助。
编辑 - MCVE:
activity_triple_list:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".controller.activities.Lists">
<include layout="@layout/content_triple_list" />
</android.support.design.widget.CoordinatorLayout>
content_triple_list:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/listsPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTabStrip
android:id="@+id/pager_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingBottom="4dp"
android:paddingTop="4dp" />
</android.support.v4.view.ViewPager>
</LinearLayout>
fragment_categories:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/categoriesFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TableLayout
android:id="@+id/categoriesTable"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:stretchColumns="4">
<TableRow
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:gravity="center_horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_marginLeft="13dp"
android:layout_marginRight="13dp"
android:orientation="vertical">
<TextView
android:id="@+id/category1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="CATEGORY 1"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</TableRow>
</TableLayout>
</LinearLayout>
fragment_items:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@id/itemsFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="@+id/itemsListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="@null" />
</LinearLayout>
content_row_choose_item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/custom_row"
android:orientation="vertical"
android:paddingBottom="5dp"
android:paddingLeft="15dp"
android:paddingTop="5dp">
<TextView
android:id="@+id/itemName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TEST"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
custom_row:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:background="#2fff00">
<item android:drawable="@color/colorPrimary" android:state_pressed="true" /> <!-- pressed -->
</selector>
ApplicationUtils:
public final class ApplicationUtils extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
ApplicationUtils.context = getApplicationContext();
}
public static Context getContext() {
return ApplicationUtils.context;
}
public static String getJavaPackageName() {
return ApplicationUtils.context.getPackageName();
}
public static Resources getAppResources() {
return getContext().getResources();
}
public static String getResouceName(Integer id) {
return getAppResources().getResourceName(id);
}
public static String getResourceString(Integer id) {
return getAppResources().getString(id);
}
public static int getResourceId(String variableName, String resourceName, String packageName) {
try {
return getContext().getResources().getIdentifier(variableName, resourceName, packageName);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
}
解释
public class Lists extends AppCompatActivity implements CategoriesFragment.OnHeadlineSelectedListener {
private String listName;
public void onItemSelected(String currentCategory) {
ItemsFragment itemsCallBackFragment = (ItemsFragment) getSupportFragmentManager().findFragmentById(R.id.itemsFragment);
if (itemsCallBackFragment != null) {
itemsCallBackFragment.updateArticleView(currentCategory);
} else {
ItemsFragment itemFragment = new ItemsFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.itemsFragment, itemFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_triple_list);
setListsAdapter();
}
private void setListsAdapter() {
ViewPager tripleListViewPager = (ViewPager) findViewById(R.id.listsPager);
FragmentPagerAdapter tripleListFragmentAdapt = new ListsPagerAdapter(getSupportFragmentManager(), "LIST NAME", ApplicationUtils.getContext());
tripleListViewPager.setAdapter(tripleListFragmentAdapt);
}
}
ListsPagerAdapter:
public class ListsPagerAdapter extends FragmentPagerAdapter {
private static int NUM_TABS = 1;
private String listName;
private Context listsContext;
public ListsPagerAdapter(FragmentManager fm, String newListName, Context listsContext) {
super(fm);
setListName(newListName);
setListsContext(listsContext);
}
// Returns total number of pages
@Override
public int getCount() {
return NUM_TABS;
}
// Returns the fragment to display for that page
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return NewItemPagerFragment.newInstance();
default:
return null;
}
}
// Returns the page title for the top indicator
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return listsContext.getResources().getString(R.string.lists_tab_newItem, getListName());
default:
return "$value";
}
}
public String getListName() {
return listName;
}
public void setListName(String listName) {
this.listName = listName;
}
public Context getListsContext() {
return listsContext;
}
public void setListsContext(Context listsContext) {
this.listsContext = listsContext;
}
}
CategoriesFragment:
public class CategoriesFragment extends Fragment {
private List<Integer> categoryIds = new ArrayList<>();
private String currentCategory;
private View categoriesView;
OnHeadlineSelectedListener itemCallback;
public interface OnHeadlineSelectedListener {
void onItemSelected(String categoryName);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
itemCallback = (OnHeadlineSelectedListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
categoriesView = inflater.inflate(R.layout.fragment_categories, container, false);
categoriesView.setId(R.id.categoriesFragment);
return categoriesView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setCategoriesListener();
setDefaultSelectedCategory();
}
private void setCategoriesListener() {
categoryIds.add(R.id.category1);
for (Integer id : categoryIds) {
setListener(id);
}
}
private void setListener(final int categoryId) {
final ImageView categoryImg = (ImageView) categoriesView.findViewById(categoryId);
categoryImg.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
removePreviousSelectedCategory(categoryImg);
selectCategory(categoryId, categoryImg);
loadItemList();
}
});
}
private void removePreviousSelectedCategory(ImageView categoryImg) {
for (Integer id : categoryIds) {
final ImageView imgView = (ImageView) categoriesView.findViewById(id);
if (imgView.getTag() != null) {
String previousSelectedCategory = (String) imgView.getTag();
if (StringUtils.contains(previousSelectedCategory, Application.SELECTED)) {
previousSelectedCategory = previousSelectedCategory.replace(Application.SELECTED, "");
categoryImg.setTag(previousSelectedCategory);
Integer previousSelectedCategoryId = ApplicationUtils.getResourceId(previousSelectedCategory, Application.RES_DRAWABLE, ApplicationUtils.getJavaPackageName());
imgView.setImageResource(previousSelectedCategoryId);
}
}
}
}
private void selectCategory(int categoryId, ImageView categoryImg) {
String newSelectedCategory = ApplicationUtils.getResouceName(categoryId) + Application.SELECTED;
setCurrentCategory(newSelectedCategory);
newSelectedCategory = newSelectedCategory.replace(Application.META_INFO_ID, "");
categoryImg.setTag(newSelectedCategory);
Integer currentCategoryId = ApplicationUtils.getResourceId(newSelectedCategory, Application.RES_DRAWABLE, ApplicationUtils.getJavaPackageName());
categoryImg.setImageResource(currentCategoryId);
}
public String getCurrentCategory() {
return currentCategory;
}
public void setCurrentCategory(String currentCategory) {
this.currentCategory = currentCategory;
}
private void loadItemList() {
itemCallback.onItemSelected(getCurrentCategory());
}
private void setDefaultSelectedCategory() {
Integer categoryId = R.id.category1;
final ImageView categoryImg = (ImageView) categoriesView.findViewById(categoryId);
selectCategory(categoryId, categoryImg);
loadItemList();
}
}
ItemsFragment:
public class ItemsFragment extends Fragment {
private View itemsFragmentView;
private ListView itemsListView;
private ItemAdapter itemsListAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
itemsFragmentView = inflater.inflate(R.layout.fragment_items, container, false);
itemsListView = (ListView) itemsFragmentView.findViewById(R.id.itemsListView);
setItemsListAdapter();
return itemsFragmentView;
}
public void updateArticleView(String categoryName) {
getSelectedCategoryList();
}
private void getSelectedCategoryList() {
List<String> testList = new ArrayList<>();
testList.add("TEST ITEM");
itemsListAdapter.update(testList);
}
private void setItemsListAdapter() {
itemsListAdapter = new ItemAdapter(getActivity(), R.layout.fragment_items, new ArrayList<String>());
itemsListView.setAdapter(itemsListAdapter);
}
}
ItemAdapter:
public class ItemAdapter extends ArrayAdapter<String> {
private List<String> items = new ArrayList<>();
private LayoutInflater rowInflater;
public ItemAdapter(Context context, int resource, List<String> itemsList) {
super(context, resource, itemsList);
this.items = itemsList;
this.rowInflater = LayoutInflater.from(context);
}
private class ItemHolder {
TextView itemNameView;
}
@Override
public View getView(int position, View rowView, ViewGroup parent) {
ItemHolder itemHolder;
if (rowView == null) {
rowView = rowInflater.inflate(R.layout.content_row_choose_item, parent, false);
itemHolder = new ItemHolder();
itemHolder.itemNameView = (TextView) rowView.findViewById(R.id.itemName);
rowView.setTag(itemHolder);
} else {
itemHolder = (ItemHolder) rowView.getTag();
}
String itemName = getItem(position);
if (StringUtils.isNotEmpty(itemName) && itemHolder.itemNameView != null) {
itemHolder.itemNameView.setText(itemName);
System.out.println("ITEM NAME ### " + itemHolder.itemNameView.getText());
}
return rowView;
}
public void update(List<String> items) {
this.items.clear();
this.items.addAll(items);
this.notifyDataSetChanged();
}
public List<String> getItems() {
return items;
}
}
答案 0 :(得分:0)
随机刺...
如果使用ListFragment
,那么fragment_items.xml
需要 ListView
android:id="@android:id/list"
。
您甚至尝试使用该ID加载ListView。
itemsFragmentView = inflater.inflate(R.layout.fragment_items, container, false);
itemsListView = (ListView) itemsFragmentView.findViewById(android.R.id.list);
但是,您有android:id="@+id/itemsListView"
<强> fragment_items:强>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@id/itemsFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ListView android:id="@+id/itemsListView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:divider="@null" /> </LinearLayout>
如果使用ListFragment,则无需实现自己的XML布局文件。话虽如此,onCreateView
不需要实现。请改用onActivityCreated
。
@Override
public void onActivityCreated(Bundle savedInstanceState) {
itemsListView = getListView();
itemsListAdapter = new ItemAdapter(getActivity());
setListAdapter(itemsListAdapter);
super.onActivityCreated(savedInstanceState);
}
现在,如果您要向适配器添加项目,我通常建议您只使用ArrayAdapter<String>
。这将为您提供add(String object)
方法,该方法将添加到基础列表并通知更新。
关于getView
问题,不能说真的。我真的不知道你为什么需要ItemAdapter
,因为默认ArrayAdapter<String>
会假设您使用android:id="@android:id/text1
传递布局,例如使用android.R.layout.simple_list_item_1
代替{{} 1}}
所以,这看起来像。
R.layout.content_row_choose_item
答案 1 :(得分:0)
给定的MCVE工作正常。经过7天的调试和取消注释代码后,我找到了问题的答案。
我的列表已正确更新,但由于在ItemsFragemnt
活动加载时初始化了第二个Lists
,因此未进行呈现。第二个片段覆盖了第一个片段,这就是为什么我没有显示/刷新我的列表。
<强>解释强>
首先创建的片段:
private void setListsAdapter() {
ViewPager tripleListViewPager = (ViewPager) findViewById(R.id.listsPager);
FragmentPagerAdapter tripleListFragmentAdapt = new ListsPagerAdapter(getSupportFragmentManager(), "LIST NAME", ApplicationUtils.getContext());
tripleListViewPager.setAdapter(tripleListFragmentAdapt); }
在ListsPagerAdapter
内,有人打电话给我的ViewPager
NewItemPagerFragment
填充CategoriesFragment
和ItemsFragment
。
第二个创建的片段 - 叠加:
ItemsFragment itemFragment = new ItemsFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.itemsFragment, itemFragment);
transaction.addToBackStack(null);
transaction.commit();
我试图破解我的代码,之前在问题范围的 Facts 中提到过,但有时这真的很痛苦。我想到了使用Log.d(TAG_KEY, TAG_NAME);
的想法,当我找到答案的时候:我意识到ItemsFragment
在活动负载上被调用了两次。
我在我的项目中搜索了new ItemsFragment
,看到我的NewItemPagerFragment
onCreate
内部正在调用ItemsFragment
。也在CategoriesFragment
之前 - 就像这样:
<强> NewItemPagerFragment:强>
Fragment itemsFragment = new ItemsFragment();
FragmentManager fm1 = getChildFragmentManager();
FragmentTransaction ft1 = fm1.beginTransaction();
ft1.replace(R.id.itemsFragment, itemsFragment);
ft1.commit();
Fragment categoriesFragment = new CategoriesFragment();
FragmentManager fm = getChildFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.categoriesFragment, categoriesFragment);
ft.commit();
解释事实2。。在NewItemPagerFragment
上评论/删除此调用后,问题就消失了。
底线为: 确保您的列表已正确实现/更新,例如notifyDataSetChanged
cricket_007 他的回答以及我在网上看到的其他一千个帖子。不要少,请确保您没有覆盖调用其初始化两次的片段。