setAdapter 在片段 Android 中不起作用

setAdapter does not work in fragment Android

我在 Activity 中使用了相同的代码并且它有效。但同样的事情在 Fragment 中不起作用。我已经放置了一些测试来检查数据库是否正确创建并发现 cursor 充满了数据。

代码如下:

public class Db_fragment extends Fragment {
    View view;
    ListView listView;
    Db_listView_Adapter db_listView_adapter;

    public Db_fragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.db_fragment, container, false);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        final MyDatabaseOpenHelper mDbHelper = new MyDatabaseOpenHelper(view.getContext());


        final EditText foodName = (EditText) view.findViewById(R.id.nameForDb);
        Button enterData = (Button) view.findViewById(R.id.enterData);
        Button showData = (Button) view.findViewById(R.id.showData);

        enterData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SQLiteDatabase myDb = mDbHelper.getWritableDatabase();
                 ContentValues contentValues = new ContentValues();
                contentValues.put(TableFoodMacros.FoodMacros.FOOD_NAME,foodName.getText().toString());
                long newRowId ;
                newRowId = myDb.insert(TableFoodMacros.FoodMacros.TABLE_NAME,null,contentValues);
                Log.e("TEST1","TEST INSERT " + String.valueOf(newRowId));

            }
        });

        showData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SQLiteDatabase myDb = mDbHelper.getReadableDatabase();

                String[] projection = {"_id",TableFoodMacros.FoodMacros.FOOD_NAME};

                Cursor c = myDb.query(
                        TableFoodMacros.FoodMacros.TABLE_NAME,
                        projection,
                        null,
                        null,
                        null,
                        null,
                        null,
                        null
                );

                Log.e("TEST3", String.valueOf(c.getCount()));
                listView = (ListView) view.findViewById(R.id.dbView);
                db_listView_adapter = new Db_listView_Adapter(view.getContext(),c);
                listView.setAdapter(db_listView_adapter);

            }
        });

    }
}

应用程序在此行崩溃:

listView.setAdapter(db_listView_adapter);

您需要从 showDataonClickListener 中删除 dbViewfindViewById 并将其放在 onCreateView 中。

所以删除以下内容。

showData.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        // ... Remove the following code segment from here. 
        listView = (ListView) view.findViewById(R.id.dbView); 
        db_listView_adapter = new Db_listView_Adapter(view.getContext(),c);
        listView.setAdapter(db_listView_adapter);

    }
});

将代码段放入 onCreateView 函数中。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.db_fragment, container, false);

    // Place the code segment here
    listView = (ListView) view.findViewById(R.id.dbView); 
    db_listView_adapter = new Db_listView_Adapter(view.getContext(),c);
    listView.setAdapter(db_listView_adapter);

    return view;
}

它在您的 Activity 中有效,因为您没有在返回的 View 中找到 ListView ID。设置 Activity 的内容视图后,您可以将 findViewById 放置在任何地方,它会完美地找到关联的布局参考。

Fragment 的情况下,如您所见 onCreateView 函数 returns 一个 View 对象作为 View 的引用,它被膨胀了。所以你需要在 View 中找到你的 ListView。这就是为什么您需要放置 view.findViewById 来搜索 ListView 中被膨胀的 View 的引用 ID。

当您将 listView = (ListView) view.findViewById(R.id.dbView); 放入 showData.setOnClickListener 中时,它会获取按钮 showData 的引用并尝试在 [=38] 中找到 dbView =] 导致错误的视图。

因此有必要在 onCreateView 中获取列表的引用并在那里设置适配器。当 cursor 填满数据时,您可以轻松地调用 notifyDatasetChanged() 重新加载列表。

顺便说一下,您也可以将代码段放入 onViewCreated 函数中,因为您可以从那里毫无问题地获取 showData 按钮的引用。所以你甚至可以把代码段放在那里。

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    final MyDatabaseOpenHelper mDbHelper = new MyDatabaseOpenHelper(view.getContext());


    final EditText foodName = (EditText) view.findViewById(R.id.nameForDb);
    Button enterData = (Button) view.findViewById(R.id.enterData);
    Button showData = (Button) view.findViewById(R.id.showData);

    // You can place the code segment here too
    listView = (ListView) view.findViewById(R.id.dbView); 
    db_listView_adapter = new Db_listView_Adapter(view.getContext(),c);
    listView.setAdapter(db_listView_adapter);

    // ... Other code goes here. 
}

您可以像这样修改 showData.setOnClickListener

showData.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            SQLiteDatabase myDb = mDbHelper.getReadableDatabase();

            String[] projection = {"_id",TableFoodMacros.FoodMacros.FOOD_NAME};

            Cursor c = myDb.query(
                    TableFoodMacros.FoodMacros.TABLE_NAME,
                    projection,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null
            );

            Log.e("TEST3", String.valueOf(c.getCount()));

            // Call notifyDatasetChanged when the cursor is filled with data to load the list. 
            db_listView_adapter.notifyDatasetChanged();

        }
    });