选择 NavigationView 菜单项时过滤 RecyclerView 卡片

Filtering RecyclerView cards when NavigationView menu item selected

我有一个 Activity 设计支持 NavigationView 实现。 抽屉有 3 个菜单项:主页、按 X 排序、按 Y 排序。 我的 activity 显示一个 RecyclerView,其中包含显示列表中数据的卡片。 该列表包含带有字符串标记("X" 或 "Y")的对象。 选择各自的菜单项时,我需要按此标签对回收库进行排序。

我的Activity activity:

当我从 Home 片段调用 setFilter 方法时出现 NPE。

public class MyActivity extends AppCompatActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    .
    .
    .
    init();
}

private void init() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mNavigationView = (NavigationView) findViewById(R.id.navigation);

    mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem) {
            Home homeFrag = new Home();
            mDrawerLayout.closeDrawers();
            switch (menuItem.getItemId()) {
                case R.id.nav_home:
                    if(!menuItem.isChecked()) {
                        setFragment(new Home());
                    }
                    break;
                case R.id.nav_x:
                    if(!menuItem.isChecked()) {
                        homeFrag.setFilter("X");
                    }
                    break;
                case R.id.nav_y:
                    if(!menuItem.isChecked()) {
                        homeFrag.setFilter("Y");
                    }
                    break;
            }
            menuItem.setChecked(true);
            mToolbar.setTitle(menuItem.getTitle());
            return true;
        }
    });
}

首页片段:

我在 filteredObjects.clear() 的 setFilter() 方法中得到一个 NPE,如果我删除它,我在 for 循环中得到一个 NPE。

public class Home extends Fragment {

private RecyclerView mRecyclerView;

List<Object> objects;
List<Object> filteredObjects;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_home, container, false);
    .
    .
    .
    mRecyclerView = (RecyclerView) v.findViewById(R.id.rv);
    LinearLayoutManager llm = new LinearLayoutManager(v.getContext());
    mRecyclerView.setLayoutManager(llm);

    objects = new ArrayList<>();
    filteredObjects = new ArrayList<>();

    initializeData(objects);
    initializeAdapter(objects);
    return v;
}

public void setFilter(String queryText) {
    queryText = queryText.toLowerCase();

    filteredObjects.clear();    // I get a NullPointerException here

    for (Object item : objects) {
        final String text = item.tag.toLowerCase();
        if (text.equals(queryText))
            filteredObjects.add(item);
    }
    initializeAdapter(filteredObjects);
}

private void initializeAdapter(List<Object> list){
    RVAdapter adapter = new RVAdapter(list);
    adapter.notifyDataSetChanged();
    mRecyclerView.setAdapter(adapter);
}

private void initializeData(List<Object> list){

    list.add(new Object("Object 1", "X"));
    list.add(new Object("Object 2", "Y"));
    list.add(new Object("Object 3", "X"));
    list.add(new Object("Object 4", "X"));
    list.add(new Object("Object 5", "Y"));
    list.add(new Object("Object 6", "Y"));
}

LOGCAT:

com.experiments.material E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.experiments.material, PID: 32273
    java.lang.NullPointerException
            at com.experiments.material.Home.setFilter(Home.java:170)
            at com.experiments.material.MyActivity.onNavigationItemSelected(MyActivity.java:134)
            at android.support.design.widget.NavigationView.onMenuItemSelected(NavigationView.java:136)
            at android.support.v7.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811)
            at android.support.v7.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:153)
            at android.support.v7.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958)
            at android.support.design.internal.NavigationMenuPresenter.onItemClick(NavigationMenuPresenter.java:179)
            at android.widget.AdapterView.performItemClick(AdapterView.java:299)
            at android.widget.AbsListView.performItemClick(AbsListView.java:1152)
            at android.widget.AbsListView$PerformClick.run(AbsListView.java:3014)
            at android.widget.AbsListView.run(AbsListView.java:3865)
            at android.os.Handler.handleCallback(Handler.java:808)
            at android.os.Handler.dispatchMessage(Handler.java:103)
            at android.os.Looper.loop(Looper.java:193)
            at android.app.ActivityThread.main(ActivityThread.java:5299)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641)
            at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
            at dalvik.system.NativeStart.main(Native Method)

编辑: activity_main.xml

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.support.design.widget.AppBarLayout
            android:layout_height="?attr/actionBarSize"
            android:layout_width="match_parent" >

            <include
                layout="@layout/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </android.support.design.widget.AppBarLayout>

        <FrameLayout
            android:name="com.experiments.material.Home"
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/navigation_items"
        app:headerLayout="@layout/header_layout" />

</android.support.v4.widget.DrawerLayout>

当你 post logcat 时,也添加 Caused by 部分。

如果您的片段不可见,您的片段将始终为空,因此 setFilter 将不起作用。试试这个代码:

在你的片段中:

private String mSetFilterString;
public Home (String filter) {
    this.mSetFilterString = filter;
}

OnCreateView

if (mSetFilterString != null) {
    setFilter(mSetFilterString);
} else {
    initializeAdapter(objects);
}    
return v;

而不是

initializeAdapter(objects);
return v;

在你的Activity中:

mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(MenuItem menuItem) {
        mDrawerLayout.closeDrawers();
        switch (menuItem.getItemId()) {
            case R.id.nav_home:
                if(!menuItem.isChecked()) {
                    getFragmentManager().beginTransaction().replace(R.id.fragment_container, (Fragment) new Home(null)).commit();
                }
                break;
            case R.id.nav_x:
                if(!menuItem.isChecked()) {
                    getFragmentManager().beginTransaction().replace(R.id.fragment_container, (Fragment) new Home("X")).commit();
                }
                break;
            case R.id.nav_y:
                if(!menuItem.isChecked()) {
                    getFragmentManager().beginTransaction().replace(R.id.fragment_container, (Fragment) new Home("Y")).commit();
                }
                break;
        }
        menuItem.setChecked(true);
        mToolbar.setTitle(menuItem.getTitle());
        return true;
    }
});

您没有初始化 filteredObjects。您只声明了它:

List<Object> filteredObjects;

您必须初始化对象。示例:

List<Object> filteredObjects= new ArrayList<Object>();