首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用ListView填充AsyncTaskLoader

使用ListView填充AsyncTaskLoader
EN

Stack Overflow用户
提问于 2013-07-05 12:40:11
回答 2查看 5.7K关注 0票数 3

我在使用AsyncTaskLoader时遇到了问题。这是我第一次尝试使用加载程序从ListView数据库中填充SQLite数据库。

一切看起来都很好,当我旋转屏幕时,数据被缓存,不再执行查询。但是当我按下“主页”按钮并再次启动我的应用程序时,数据就会再次加载。

NoteUsuario的意思是User,所以我正在用用户列表填充ListView

代码语言:javascript
复制
public class Main extends SherlockFragmentActivity
        implements LoaderManager.LoaderCallbacks<ArrayList<Usuario>> {
    UsuarioAdapter adapter;
    ListView listView;
    Database db;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        listView = (ListView) findViewById(R.id.lista);
        db       = new Database(this);
        adapter  = new UsuarioAdapter(this, new ArrayList<Usuario>());
        listView.setAdapter(adapter);
        getSupportLoaderManager().initLoader(0, null, this);
    }

    @Override
    public Loader<ArrayList<Usuario>> onCreateLoader(int id, Bundle args) {
        return new UsuariosLoader(this, db);
    }

    @Override
    public void onLoadFinished(Loader<ArrayList<Usuario>> loader,
                           ArrayList<Usuario> usuarios) {
       //adapter.notifyDataSetChanged();
      listView.setAdapter(new UsuarioAdapter(this, usuarios));
      // ((BaseAdapter) listView.getAdapter()).notifyDataSetChanged();
    }

    @Override
    public void onLoaderReset(Loader<ArrayList<Usuario>> loader) {
        listView.setAdapter(null);
    }
}

// THE LOADER
class UsuariosLoader extends AsyncTaskLoader<ArrayList<Usuario>> {
    private ArrayList<Usuario> usuarios;
    private Database db;

    public UsuariosLoader(Context context, Database db) {
        super(context);
        this.db = db;
    }

    @Override
    protected void onStartLoading() {
        if (usuarios != null) {
          deliverResult(usuarios); // Use the cache
        }
       forceLoad();
    }

    @Override
    protected void onStopLoading() {
        // The Loader is in a stopped state, so we should attempt to cancel the
        // current load (if there is one).
        cancelLoad();
    }

    @Override
    public ArrayList<Usuario> loadInBackground() {              
        db.open();  // Query the database
        ArrayList<Usuario> usuarios = db.getUsuarios();
        db.close();
        return usuarios;
    }

    @Override
    public void deliverResult(ArrayList<Usuario> data) {
        usuarios = data; // Caching
        super.deliverResult(data);
    }

    @Override
    protected void onReset() {
       super.onReset();
       // Stop the loader if it is currently running
       onStopLoading();
       // Get rid of our cache if it exists
       usuarios = null;
    }

    @Override
    public void onCanceled(ArrayList<Usuario> data) {
       // Attempt to cancel the current async load
       super.onCanceled(data);
       usuarios = null;
   }
}

我觉得这个片段做得不好。我正在创建一个新的适配器,而不是更新数据。

代码语言:javascript
复制
    @Override
    public void onLoadFinished(Loader<ArrayList<Usuario>> loader,
                           ArrayList<Usuario> usuarios) {
        //adapter.notifyDataSetChanged();
        listView.setAdapter(new UsuarioAdapter(this, usuarios));
        //((BaseAdapter) listView.getAdapter()).notifyDataSetChanged();
    }

为什么adapter.notifyDataSetChanged()不能工作?

因此,基本上,我的应用程序不会崩溃,但每次重新启动应用程序时,我的所有数据都会重新加载。

编辑:这是我的适配器代码:

代码语言:javascript
复制
    class UsuarioAdapter extends BaseAdapter {
    private ArrayList<Usuario> usuarios;
    private LayoutInflater inflater;

    public UsuarioAdapter(Context context, ArrayList<Usuario> usuarios) {
        this.usuarios = usuarios;
        this.inflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() { return usuarios.size(); }
    @Override
    public Object getItem(int pos) { return usuarios.get(pos); }
    @Override
    public long getItemId(int pos) { return pos; }

    @Override
    public View getView(int pos, View convertView, ViewGroup arg) {
        LinearLayout itemView;
        if (convertView == null) {
            itemView = (LinearLayout) inflater.inflate(R.layout.list_item, null);
        } else {
            itemView = (LinearLayout) convertView;
        }

        ImageView avatar = (ImageView) itemView.findViewById(R.id.avatar);
        TextView nombre  = (TextView) itemView.findViewById(R.id.nombre);
        TextView edad    = (TextView)itemView.findViewById(R.id.edad);

        // Set the image ... TODO
        nombre.setText(usuarios.get(pos).getNombre());
        edad.setText(String.valueOf(usuarios.get(pos).getEdad()));
        return itemView;
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-07-05 18:03:19

我找到了解决办法。onStartLoading是有罪的:

代码语言:javascript
复制
    @Override
    protected void onStartLoading() {
        if (usuarios != null) {
            deliverResult(usuarios); // Use cache
        } else {
            forceLoad();
        }
    }

在我最初的帖子中,forceLoad总是被称为。它一定在else分支中。

票数 2
EN

Stack Overflow用户

发布于 2013-07-05 12:47:18

notifyDataSetChanged()的调用不会更改适配器正在使用的数据。您需要更新适配器所拥有的数据,然后调用该方法。

NotifyDataSetChanged()只会告诉适配器它需要创建它的视图,但是它不会更改数据。你得自己处理。

在适配器中添加:

代码语言:javascript
复制
public void setUsuario(List<Usuario> usuarios) {
    this.usuarios = usuarios;
}

然后在onLoadFinished()中调用新方法,然后调用notifyDataSetChanged()

代码语言:javascript
复制
listView.getAdapter().setUsuario(usuarios);
listView.getAdapter().notifiyDataSetChanged();
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17489145

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档