loadinBackground()配置改变期间调用

问题描述 投票:2回答:3

我在做一个应用程序,它显示邮编列表(ListView中),当我点击它,它使用OpenWeather API显示我详细的天气报告。邮编的列表存储在SQLite数据库和,我使用AsyncTaskLoader从中检索数据。数据被正确显示。问题是配置改变,loadinBackground()方法被调用,其不应该发生期间。

public class DataLoader extends AsyncTaskLoader<List<RowItem>> 
{
Context activityContext;
private String TAG="DataLoader";
public DataLoader(Context context)
{
    super(context);
    this.activityContext = context;
}

@Override
public List<RowItem> loadInBackground()
{
    Log.v(TAG, "loadinBackground() IN");
    List<RowItem> rowItems = new ArrayList<RowItem>();
    DbReaderHelper mDbHelper = new DbReaderHelper(activityContext);
    SQLiteDatabase db = mDbHelper.getReadableDatabase();
    String[] columns = {DbReaderHelper.COLUMN_CITYNAME,DbReaderHelper.COLUMN_ZIPCODE};
    Cursor cur =  db.query(DbReaderHelper.TABLE_NAME, columns,null,null,null,null,null);
    cur.moveToFirst();
    while(!cur.isAfterLast())
    {
        String city = cur.getString(cur.getColumnIndex(DbReaderHelper.COLUMN_CITYNAME));
        String zipcode = cur.getString(cur.getColumnIndex(DbReaderHelper.COLUMN_ZIPCODE));
        rowItems.add(new RowItem(city,Integer.parseInt(zipcode)));
        cur.moveToNext();
    }
    cur.close();    // release all the resources
    db.close();
    mDbHelper.close();
    Log.v(TAG, "loadinBackground() OUT");
    return rowItems;
}
}

这里是装载机回调的实现

public class ListFragment extends Fragment implements LoaderManager.LoaderCallbacks<List<RowItem>>
{
private TextView emptyListTV;
private EditText zipcodeET;
private CustomAdapter customAdapter;
private List<RowItem> rowItems;
private ListView listView;
private final String TAG = "ListFragment";
private boolean fromRemoveItemFromListView = false;     // TODO check this again
private final int  LOADER_ID = 0x0;

public ListFragment()
{
    // empty constructor
}

@Override
public void onCreate(Bundle savedInstanceState)
{
    Log.v(TAG,"onCreate() IN");
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    Log.v(TAG,"onCreate() OUT");
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    // Inflate the layout for this fragment
     View view = inflater.inflate(R.layout.fragment_list, container, false);
     initializeLayoutViews(view);
    return view;
}

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);
    setRetainInstance(true);
    getLoaderManager().initLoader(LOADER_ID,null,this).forceLoad();
}

@Override
public Loader<List<RowItem>> onCreateLoader(int id, Bundle args)
{
    Toast.makeText(getActivity(),"onCreateLoader()",Toast.LENGTH_SHORT).show();
    return new DataLoader(getActivity());
}

@Override
public void onLoadFinished(Loader<List<RowItem>> loader, List<RowItem> rowItems)
{
    Toast.makeText(getActivity(),"onLoadFinished",Toast.LENGTH_SHORT).show();
    customAdapter.setData(rowItems);
    customAdapter.notifyDataSetChanged();
    setMessageIfListEmpty();
}

@Override
public void onLoaderReset(Loader<List<RowItem>> loader)
{
    Toast.makeText(getActivity(),"onLoaderReset()",Toast.LENGTH_SHORT).show();
    customAdapter.setData(new ArrayList<RowItem>());
    customAdapter.notifyDataSetChanged();
}
}

这是我的日志时改变方向

01-31 22:07:12.532  15019-15019/com.siddhant.myweatherapp D/AbsListView﹕ onDetachedFromWindow
01-31 22:07:12.583  15019-15019/com.siddhant.myweatherapp I/PersonaManager﹕ getPersonaService() name persona_policy
01-31 22:07:12.583  15019-15019/com.siddhant.myweatherapp V/MainActivity﹕ onCreate() IN
01-31 22:07:12.653  15019-15019/com.siddhant.myweatherapp V/MainActivity﹕ onStart() IN
01-31 22:07:12.733  15019-15019/com.siddhant.myweatherapp D/AbsListView﹕ Get MotionRecognitionManager
01-31 22:07:12.743  15019-15019/com.siddhant.myweatherapp V/ListFragment﹕ onLoadFinished() IN
01-31 22:07:12.743  15019-15019/com.siddhant.myweatherapp V/ListFragment﹕ onLoadFinished() OUT
01-31 22:07:12.743  15019-15019/com.siddhant.myweatherapp V/ListFragment﹕ onLoadFinished() IN
01-31 22:07:12.743  15019-15019/com.siddhant.myweatherapp V/ListFragment﹕ onLoadFinished() OUT
01-31 22:07:12.743  15019-15019/com.siddhant.myweatherapp V/MainActivity﹕ onStart() OUT
01-31 22:07:12.753  15019-15019/com.siddhant.myweatherapp V/MainActivity﹕ OnResume() IN
01-31 22:07:12.753  15019-15522/com.siddhant.myweatherapp V/DataLoader﹕ loadinBackground() IN
01-31 22:07:12.753  15019-15019/com.siddhant.myweatherapp V/MainActivity﹕ onResume() OUT
01-31 22:07:12.803  15019-15019/com.siddhant.myweatherapp E/ViewRootImpl﹕ sendUserActionEvent() mView == null
01-31 22:07:12.813  15019-15019/com.siddhant.myweatherapp V/MainActivity﹕ onCreateOptionsMenu() IN
01-31 22:07:12.813  15019-15019/com.siddhant.myweatherapp V/MainActivity﹕ onCreateOptionsMenu() OUT
01-31 22:07:12.953  15019-15522/com.siddhant.myweatherapp V/DataLoader﹕ loadinBackground() OUT
01-31 22:07:12.963  15019-15019/com.siddhant.myweatherapp V/ListFragment﹕ onLoadFinished() IN
01-31 22:07:12.963  15019-15019/com.siddhant.myweatherapp V/ListFragment﹕ onLoadFinished() OUT

谢谢,

android loader asynctaskloader
3个回答
0
投票

您对forceLoad()返回装载机调用initLoader()。这将导致加载器加载的数据,即使它已经检索到之前的数据。你不应该需要调用此方法,只需调用initLoader()


0
投票

forceLoad()不会自动调用,但需要启动数据的加载。

然而forceLoad()应该onStartLoading()内完成,而不是呼吁initLoader()

AsyncTaskLoaders从API等级28(安卓派)起弃用。


0
投票

不同于自动运行后台任务,当你调用AsyncTask,该myAsyncTask.execute()没有自动运行后台线程,当你调用AsyncTaskLoader getSupportLoaderManager().initLoader(MY_LOADER_ID, null, this);执行它运行,你需要通过两种方式显式调用的forceload()Loader对象在后台线程:

第一:通过方法链初始化/启动加载器与getSupportLoaderManager().initLoader(MY_LOADER_ID, null, this).forceLoad();的LoaderManager时

第二:在自定义的类装载器回调onStartLoading()是自动触发的getSupportLoaderManager().initLoader(...)

@Override
protected void onStartLoading() {
    super.onStartLoading();
    forceLoad(); // call loadInBackground()
}

显然,对配置变化,这两种方法将调用loadInBackground()方法,因为onCreate()方法将在屏幕旋转被触发之后getSupportLoaderManager().initLoader(...)forceLoad()将相应地调用,但隐含您可以利用第二种方法通过使用loadInBackground()方法必要时停止通话deliverResult()这提供先前的负载到注册监听器的onLoadFinished()方法,这反过来又使我们能够跳过loadInBackground()调用的结果。

所以,你需要在自己的代码来改变:

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);
    setRetainInstance(true);
    getLoaderManager().initLoader(LOADER_ID, null, this);
}

这里是装载机

public class DataLoader extends AsyncTaskLoader<List<RowItem>> {

    Context activityContext;
    private String TAG="DataLoader";
    private List<RowItem> rowItems;

    public DataLoader(Context context){
        super(context);
        this.activityContext = context;
    }

    @Override
    protected void onStartLoading() {
        super.onStartLoading();
        if (rowItems != null) {
            deliverResult(rowItems); // skip loadInBackground() call
        } else {
            forceLoad(); // call loadInBackground()
        }
    }


    @Override
    public List<RowItem> loadInBackground(){
        Log.v(TAG, "loadinBackground() IN");
        rowItems = new ArrayList<RowItem>();
        DbReaderHelper mDbHelper = new DbReaderHelper(activityContext);
        SQLiteDatabase db = mDbHelper.getReadableDatabase();
        String[] columns = {DbReaderHelper.COLUMN_CITYNAME,DbReaderHelper.COLUMN_ZIPCODE};
        Cursor cur =  db.query(DbReaderHelper.TABLE_NAME, columns,null,null,null,null,null);
        cur.moveToFirst();
        while(!cur.isAfterLast())
        {
            String city = cur.getString(cur.getColumnIndex(DbReaderHelper.COLUMN_CITYNAME));
            String zipcode = cur.getString(cur.getColumnIndex(DbReaderHelper.COLUMN_ZIPCODE));
            rowItems.add(new RowItem(city,Integer.parseInt(zipcode)));
            cur.moveToNext();
        }
        cur.close();    // release all the resources
        db.close();
        mDbHelper.close();
        Log.v(TAG, "loadinBackground() OUT");
        return rowItems;
    }
}

值得一提的是Loaders已被弃用的Android P(API 28)。

© www.soinside.com 2019 - 2024. All rights reserved.