Android加载器启动时单击然后方向已更改 - 不再提供数据

时间:2014-02-01 22:00:17

标签: android android-loadermanager android-loader

正如标题所说的那样,我在点击按钮时开始Loader,然后我正在进行方向更改。在重新创建的活动中,onLoadFinished在启动时不会自动调用。我怀疑LoaderManager不知道这个新创建的活动实例,因为我不认为它与活动生命周期紧密相关。但我可能错了......

这是加载器,提供一个字符串数组并模拟它延迟数据结果3秒。实施是AsyncTaskLoader sample code的简化版。

import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;

public class ContentAsyncLoader extends AsyncTaskLoader<String[]> {
    private String[] data;

    public ContentAsyncLoader(Context context) {
        super(context);
    }

    @Override
    protected void onStartLoading() {
        if (data != null) {
            deliverResult(data);
        } else {
            forceLoad();
        }
    }

    @Override
    public String[] loadInBackground() {
        synchronized (this) {
            try {
                wait(3000);
            } catch (InterruptedException e) {
            }
        }
        final String[] result = { "Dell Inspiron", "HTC One X", "HTC Wildfire S", "HTC Sense", "HTC Sensation XE", "iPhone 4S", "Samsung Galaxy Note 800", "Samsung Galaxy S3", "MacBook Air",
                "Mac Mini", "MacBook Pro" };
        return result;
    }

    @Override
    protected void onStopLoading() {
        cancelLoad();
    }

    @Override
    protected void onReset() {
        super.onReset();
        onStopLoading();
        data = null;
    }

    @Override
    public void deliverResult(String[] data) {
        if (isReset()) {
            return;
        }
        this.data = data;
        if (isStarted()) {
            super.deliverResult(data);
        }
    }
}

以下是按钮点击启动加载程序的活动 - ListViewButton

public class MainActivity extends FragmentActivity implements OnClickListener, LoaderCallbacks<String[]> {

    private static final int LOADER_ID = 1;
    private ListView lv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv = (ListView) findViewById(R.id.list_view);
        findViewById(R.id.btnSomeAction).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        getSupportLoaderManager().initLoader(LOADER_ID, null, this);
    }

    @Override
    public Loader<String[]> onCreateLoader(int id, Bundle bundle) {
        ContentAsyncLoader loader = new ContentAsyncLoader(this);
        return loader;
    }

    @Override
    public void onLoaderReset(Loader<String[]> loader) {
    }

    @Override
    public void onLoadFinished(Loader<String[]> loader, String[] data) {
        if (data != null) {
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, data);
            lv.setAdapter(adapter);
        }
    }
}

如果有人想要一个明确的问题:如何正确使用按钮点击启动的Loader,以便在重新创建活动时自动重新提供数据?

我有一些肮脏的解决方法,通过在单击按钮时将标志设置为true来解决此问题,在调用onSaveInstanceState时将其保存,然后在onCreate中检查它是否存在,如果存在则致电initLoader;但我讨厌在这种情况下有这个,当我从一个活动开始不同的加载器时,我需要为每个这样的加载器保留一个标志,因为我倾向于懒惰...例如:

private boolean loaderCreated;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    lv = (ListView) findViewById(R.id.list_view);
    findViewById(R.id.btnSomeAction).setOnClickListener(this);
    if (savedInstanceState != null) {
        loaderCreated = savedInstanceState.getBoolean("TEMP", false);
        if(loaderCreated) {
            getSupportLoaderManager().initLoader(LOADER_ID, null, this);
        }
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean("TEMP", loaderCreated);
}

@Override
public void onClick(View v) {
    loaderCreated = true;
    getSupportLoaderManager().initLoader(LOADER_ID, null, this);
}

有没有更好的方法呢?

1 个答案:

答案 0 :(得分:3)

每次按下按钮之前,

getSupportLoaderManager().initLoader(LOADER_ID, null, this);都应调用onCreate

因为现在在方向savedInstanceState不为空并且您没有向加载程序询问数据之后。

我看到你做到了......;)而这只是唯一的方式。

此致