Android ListView未显示/刷新且getView无法正常工作

时间:2016-10-09 17:27:16

标签: android listview android-fragments android-adapter

目标:我有一个活动,在两个片段中。 ideia用于传递两个片段,选择一个类别并更新其项目列表。在活动加载时,默认情况下会定义一个类别。

问题:在活动加载时,ItemsFragment不显示/更新itemsLisView。此外,ItemAdapter的getView方法仅被调用两次,即使该列表有五个项目。

事实:

  1. 在传递给适配器
  2. 之前正确地履行了项目列表
  3. 打破代码,不确定原因或是否重要,在CategoriesFragments之前渲染/调用ItemsFragment。我发现这很奇怪,因为CategoriesFragments位于ItemsFragment之上。这就是我写if (getArguments() != null)的原因。在我获得Null指针异常之前。
  4. 研究:关于这两个主题存在很多问题。

    1. Android ListView not refreshing after notifyDataSetChanged with data as Map
    2. ListFragment Not Rendering and getView() in Adapter Not Being Called
    3. Android getView() not being called properly?
    4. BaseAdapter notifyDatasetChanged() called but getView() is never called
    5. 这些是我经历过的一些链接示例(成千上万),试图为我的案例找到解决方案。不幸的是,他们都没有工作。

      我已经在这个问题上待了将近5天了,我想我在这里错过了一些Android概念。它与Java编程无关,或者至少我希望如此。

      问题:

      1. 为什么ItemsFragment没有在活动加载中显示项目列表? (这可能会解决更新问题)
      2. 为什么ItemAdapter只调用getView两次,即使项目列表正确地给了他更多的项目?
      3. 如需了解更多信息,请不要随意询问。 提前感谢您的帮助。

        编辑 - 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;
            }
        }
        

2 个答案:

答案 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填充CategoriesFragmentItemsFragment

第二个创建的片段 - 叠加:

        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 他的回答以及我在网上看到的其他一千个帖子。不要少,请确保您没有覆盖调用其初始化两次的片段