CursorAdapter: newView и bindView никогда не вызывались - PullRequest
0 голосов
/ 06 июля 2018

Я пытаюсь создать ListView, который должен заполняться данными, полученными с SQLiteDatabase. Для этого я создал специальный адаптер, наследующий от ResourceCursorAdapter. В моей основной деятельности у меня есть кнопка, которая при нажатии создает фрагмент, который должен отображать мой список. Однако, хотя кажется, что я правильно установил адаптер на ListView (конструктор вызывается) newView и bindView никогда не вызывается. Я создал свой адаптер, следуя этому небольшому руководству: https://github.com/codepath/android_guides/wiki/Populating-a-ListView-with-a-CursorAdapter

Чего мне не хватает?

из моей деятельности:

loadSnapshotsButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // some static extra items
        final MatrixCursor extras = new MatrixCursor(new String[]{
                SettingsContract.PixelSnapshotEntries._ID,
                SettingsContract.PixelSnapshotEntries.SNAPSHOT_NAME,
                SettingsContract.PixelSnapshotEntries.SNAPSHOT_SIZE
        });
        extras.addRow(new String[]{"-1", "export snapshots set...", null});
        extras.addRow(new String[]{"-2", "load snapshots set...", null});
        final String[] settingsFields = new String[]{
                SettingsContract.PixelSnapshotEntries._ID,
                SettingsContract.PixelSnapshotEntries.SNAPSHOT_NAME,
                SettingsContract.PixelSnapshotEntries.SNAPSHOT_SIZE
        };
        final Cursor cursor = mDb.query(
                SettingsContract.PixelSnapshotEntries.TABLE_NAME,
                settingsFields,
                null, null, null, null, null
        );
        final Cursor[] cursors = {cursor, extras};
        final MergeCursor mergedCursor = new MergeCursor(cursors);
        Log.d(TAG, "num results: " + mergedCursor.getCount());

        SelectSnapshotFragment snapshotSelect = new SelectSnapshotFragment();
        fragmentManager
                .beginTransaction()
                .add(R.id.camera_preview, snapshotSelect, "snapshot select")
                .commit();
        // creation of the list view is happening in the fragment
        // in order to avoid asyncronicity issues
        snapshotSelect.setCursor(mergedCursor);
        cursor.close();
        extras.close();
    }

onCreateView из фрагмента:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.snapshots_list, container, false);
    final ListView snapshotsListView = (ListView) view.findViewById(R.id.snapshots_list);
    final SnapshotSelectAdapter adapter = new SnapshotSelectAdapter(getActivity(), R.layout.snapshots_item, mCursor, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
    snapshotsListView.setAdapter(adapter);
    // check for the adapter to be set properly - OK
    Log.d(TAG, "snapshots list view: " + snapshotsListView.getAdapter());
    mCursor.close();
    container.addView(view);
    return super.onCreateView(inflater, container, savedInstanceState);
}

мой пользовательский адаптер:

public class SnapshotSelectAdapter extends ResourceCursorAdapter {
    final private static String TAG = "SnapshotSelectAdapter";
    private int mLayout;

    public SnapshotSelectAdapter(Context context, int layout, Cursor c, int flags) {
        super(context, layout, c, flags);
        // cursor holds the right number of items - OK
        Log.d(TAG, "cursor: " + c.getCount());
        mLayout = layout;
    }

    // never called
    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return LayoutInflater.from(context).inflate(mLayout, parent, false);
    }

    // never called either
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        TextView row = (TextView) view.findViewById(R.id.snapshot_item);
        Log.d(TAG, "view: " + view + ", row: " + row);
        String text = cursor.getString(cursor.getColumnIndexOrThrow(SettingsContract.PixelSnapshotEntries.SNAPSHOT_NAME)) + " (" +
            String.valueOf(cursor.getInt(cursor.getColumnIndexOrThrow(SettingsContract.PixelSnapshotEntries.SNAPSHOT_SIZE))) + ")";
        row.setText(text);
    }

snapshots_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/snapshots_selection"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="@color/colorDarkTransparentBackground"
          android:animateLayoutChanges="true"
          android:orientation="vertical">

    <ListView
        android:id="@+id/snapshots_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="20dp"
        android:paddingEnd="20dp"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:paddingStart="20dp"
        android:paddingTop="5dp"/>

</LinearLayout>

snapshots_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="15dp"
        android:paddingTop="15dp"
        android:textSize="20sp"
        android:id="@+id/snapshot_item" />

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

После некоторой борьбы я думаю, что нашел решение. Проблема, насколько я вижу, лежала в пределах onCreateView моего фрагмента. Я явно прикрепил представление к контейнеру. После удаления этой строки newView и bindView там, где она вызывается, как и ожидалось:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final ScrollView bg = (ScrollView) inflater.inflate(R.layout.settings_background_scroll, container, false);
    final View view = inflater.inflate(R.layout.snapshots_list, bg, false);
    final ListView snapshotsListView = (ListView) view.findViewById(R.id.snapshots_list);
    final SnapshotSelectAdapter adapter = new SnapshotSelectAdapter(getActivity(), R.layout.snapshots_item, mCursor, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
    snapshotsListView.setAdapter(adapter);
    return view;
}
0 голосов
/ 06 июля 2018

Я вижу проблему в вашем onCreateView в вашем фрагменте.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.snapshots_list, container, false);
    final ListView snapshotsListView = (ListView) view.findViewById(R.id.snapshots_list);
    final SnapshotSelectAdapter adapter = new SnapshotSelectAdapter(getActivity(), R.layout.snapshots_item, mCursor, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
    snapshotsListView.setAdapter(adapter);
    // check for the adapter to be set properly - OK
    Log.d(TAG, "snapshots list view: " + snapshotsListView.getAdapter());
    return view
}

Вы должны вернуть представление из этого метода, вам не нужно прикреплять к контейнеру вручную.

Не закрывать курсор в onCreateView, пока адаптер еще не прочитал и не инициализировал строки списка. Пожалуйста, проверьте этот ответ , чтобы понять, где закрыть курсор.

Возможно, закрытие курсора должно происходить в методе onStop(), и тогда вы

В конце я бы посоветовал не использовать устаревшие учебники.

С тех пор вы можете использовать RecyclerView вместо ListView и Room вместо ручной обработки курсоров и курсора адаптера курсора.

Если у вас очень большой список в вашей базе данных, вы можете использовать Pagination Library. Для этого я бы посоветовал проверить Google I / O о списках и нумерации страниц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...