如何在片段中使用Retrofit和Loader类

时间:2016-08-25 03:10:36

标签: android android-fragments retrofit loader android-databinding

我使用Retrofit从我的RESTful接收json,这很好。我试图实现Loader类以使数据加载逻辑更加清晰,而不是将其放入onCreateView方法来加载它,这对于加载数据来说并不是一个明确的逻辑。但是,如果我尝试使用AsyncTaskLoader(一个应该从异步进程接收数据的那个)进行改造,我发现有点困惑。我坚持这一点。 Retrofit已经是一个异步过程,我想我应该在AsyncLoader类的改进中使用异步调用或同步调用。

package generic.fragment;
import android.databinding.ViewDataBinding;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;

import java.util.ArrayList;
import java.util.List;

import generic.adapter.BaseListAdapter;

public abstract class SwipedLoaderListFragment<Bean, Adapter extends BaseListAdapter<Bean, ? extends ViewDataBinding>> extends SwipedListFragment<Bean, Adapter> implements LoaderManager.LoaderCallbacks<List<Bean>> {
    public SwipedLoaderListFragment(FragConfig pFragConfig) {
        super(pFragConfig);
    }
    @Override
    public List<Bean> loadData(String query) {
        List<Bean> list = new ArrayList<>();
        return list;
    }
    @Override
    public void refreshing() {
        getLoaderManager().restartLoader(0, null, this);
    }
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getLoaderManager().initLoader(0, null, this).forceLoad();
    }
    @Override
    public void onLoadFinished(Loader<List<Bean>> loader, List<Bean> data) {
        mAdapter.clear();
        mAdapter.addAll(data);
    }
    @Override
    public void onLoaderReset(Loader<List<Bean>> loader) {
        mAdapter.clear();
    }
}

这是我用过的片段。

public class LocListFragment extends SwipedLoaderListFragment<String, SimpleStringAdapter> {
    public LocListFragment() {
        super(new FragConfigBuilder(R.layout.swiped_list).setEnableSwipe(false).setFilterable(true).setEnableDivider(true).build());
    }
    @Override
    public void query(String query) {
        super.query(query);
        mAdapter.filter(query);
    }
    @Override
    public void queryWhenTextChanged(String query) {
        super.queryWhenTextChanged(query);
        mAdapter.filter(query);
    }
    @Override
    public SimpleStringAdapter initListAdapter() {
        return new SimpleStringAdapter(getActivity(), loadData("")) {
            @Override
            public ListItemStringBinding bind(ListItemStringBinding pBinding, String pS, int pPosition) {
                pBinding.setText(pS);
                return pBinding;
            }
        };
    }
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Intent lIntent = new Intent();
        lIntent.putExtra(SCConstants.PARAM_LOC, mAdapter.getItem(position));
        getActivity().setResult(Activity.RESULT_OK, lIntent);
        getActivity().finish();
    }
    @Override
    public String getHintStr() {
        return "Input Location";
    }
    @Override
    public String getSearchTitle() {
        return "Location Search";
    }
    @Override
    public Loader<List<String>> onCreateLoader(int id, Bundle args) {
        return new AsyncTaskLoader<List<String>>(getActivity()) {
            @Override
            public List<String> loadInBackground() {
                //here will be the retrofit call
                return null;
        };
    }
}

1 个答案:

答案 0 :(得分:1)

由于Loader的loadInBackground方法已经异步,因此使用同步改装调用可能更容易(即使用execute而不是enqueue)。

要使您的装载机正常工作,您还需要覆盖onStartLoading。实现可能如下所示:

public class MyLoader<List<String>> extends AsyncTaskLoader {
    List<String> mResult;

    @Override
    public List<String> loadInBackground() {
         mResult = myHttpApi.execute()...
         return mResult;
    }

    @Override
    protected void onStartLoading() {
         if (mResult != null) {
             deliverResult(mResult);
         }
         if (mResult == null || takeContentChanged()) {
             forceLoad();
         }
    }
}