Как заполнить счетчик с помощью CursorLoader?

Я пытаюсь заполнить счетчик из курсорного загрузчика.

У меня есть IndicatorFragment для счетчика, который я собираюсь включить в некоторые другие фрагменты (через тег <include>).


Первым делом я проверил, есть ли данные в базе данных (ContentProvider), и все в порядке.


Вторым шагом было написать xml файл:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:text="@string/con_lbl_input_indicator"
            android:textSize="22sp"
            android:textStyle="bold"
            android:layout_marginTop="8dp"
            android:layout_marginLeft="5dp"/>

        <Spinner
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:id="@+id/indicators_spinner"
            android:layout_gravity="bottom"
            android:spinnerMode="dropdown" />
    </LinearLayout>
</merge>

Затем я написал IndicatorFragment.class, где я использую SimpleCursorAdapter и Loader для заполнения данных из базы данных:

public class IndicatorsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{

    private static final String LOG_TAG = IndicatorsFragment.class.getSimpleName();

    private static final int INDICATOR_LOADER_ID = 0;

    private Spinner spIndicator;
    private SimpleCursorAdapter spinAdapter;

    private static final String[] INDICATOR_PROJECTION = {
            ChemToolsContract.IndicatorsEntry._ID,
            ChemToolsContract.IndicatorsEntry.COLUMN_NAME
    };

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

        spIndicator = (Spinner) rootView.findViewById(R.id.indicators_spinner);

        spinAdapter = new SimpleCursorAdapter(getActivity(),
                android.R.layout.simple_spinner_item, null,
                new String[]{ChemToolsContract.IndicatorsEntry.COLUMN_NAME},
                new int[] {android.R.id.text1}, 0);

        spinAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        spIndicator.setAdapter(spinAdapter);

        spIndicator.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

            }
        });

        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        getLoaderManager().initLoader(INDICATOR_LOADER_ID, null, this);
        spIndicator.setOnItemClickListener(null);
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onPause() {
        getLoaderManager().destroyLoader(INDICATOR_LOADER_ID);
        super.onPause();
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Uri baseUri = ChemToolsContract.IndicatorsEntry.CONTENT_URI;

        return new CursorLoader(getActivity(), baseUri, INDICATOR_PROJECTION, null, null, null);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        spinAdapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        spinAdapter.swapCursor(null);
    }
}

И последнее, это xml файл, куда я добавил свой фрагмент со спиннером, используя атрибут <include>:

<include layout="@layout/fragment_indicators"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"/>

Но я не вижу никаких данных в счетчике при запуске приложения:

http://i.stack.imgur.com/bgi9R.png


Так что я не знаю, что я делаю неправильно: загружаю данные из базы данных или включаю фрагмент со спиннером в другую?


person c0nst    schedule 30.05.2015    source источник
comment
где ваш метод БД, в котором вы получаете значение столбца IndicatorsEntry   -  person Keshav1234    schedule 30.05.2015
comment
Я думал, что Loader обрабатывает метод query() ContentProvider. В любом случае это мой класс ContentProvider: gist.github.com/anonymous/b290fbaa2947982fd28d   -  person c0nst    schedule 30.05.2015
comment
используйте отладчик и проверьте, правильно ли вы получаете данные из БД.   -  person Keshav1234    schedule 30.05.2015
comment
У меня та же реализация CursorLoader, которую я использовал в других фрагментах. В этих фрагментах все работает правильно. Я думаю, что, может быть, я делаю что-то не так с SimpleCursorAdapter?   -  person c0nst    schedule 30.05.2015
comment
в простом адаптере курсора, почему вы передаете null для курсора?   -  person Keshav1234    schedule 30.05.2015
comment
курсор содержит значения базы данных, поскольку вы передаете null, значения не отображаются.   -  person Keshav1234    schedule 30.05.2015
comment
Я использовал тот же подход, но сразу же исправил его ошибку (new int[] {android.R.id.text1} в конструкторе SimpleCursorAdapter): stackoverflow.com/questions/12434413/   -  person c0nst    schedule 30.05.2015


Ответы (2)


Вы должны инициализировать Loader, эта строка отсутствует. Предлагаю включить эту строку:

getLoaderManager().initLoader(INDICATOR_LOADER_ID, null, this);

внутри метода onCreateView, чуть выше строки return rootView;. Метод в этом случае должен быть таким:

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

    spIndicator = (Spinner) rootView.findViewById(R.id.indicators_spinner);

    spinAdapter = new SimpleCursorAdapter(getActivity(),
            android.R.layout.simple_spinner_item, null,
            new String[]{ChemToolsContract.IndicatorsEntry.COLUMN_NAME},
            new int[] {android.R.id.text1}, 0);

    spinAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

    spIndicator.setAdapter(spinAdapter);

    spIndicator.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

        }
    });
    getLoaderManager().initLoader(INDICATOR_LOADER_ID, null, this);
    return rootView;
}

Удачного кодирования!

person Reynel Fals de Pedro    schedule 06.04.2016

Любопытно, что вы не столкнулись со следующей ошибкой (потому что я столкнулся).

java.lang.RuntimeException: setOnItemClickListener cannot be used with a spinner. 

Тем не менее, отличный ответ от @Reynel. Просто небольшое редактирование, которое я хотел бы сделать. Вместо

spIndicator.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    }
});

ты пишешь

spIndicator.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        // you code here
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        // you code here
    }
});

Взято из этого post.

person remykarem    schedule 11.10.2017