3

我在使用AsyncTaskLoader. 这是我第一次尝试使用加载器从SQLite数据库填充ListView 。

一切似乎都很好,当我旋转屏幕时,数据被缓存并且不再进行任何查询。但是当我按下主页按钮并再次启动我的应用程序时,数据会再次加载。

注意Usuario意味着User,所以我用用户列表填充ListView

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;
   }
}

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

    @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()不工作?

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

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

    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;
    }
}
4

2 回答 2

3

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

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

在您的适配器中添加:

public void setUsuario(List<Usuario> usuarios) {
    this.usuarios = usuarios;
}

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

listView.getAdapter().setUsuario(usuarios);
listView.getAdapter().notifiyDataSetChanged();
于 2013-07-05T12:47:18.050 回答
2

我找到了解决方案。onStartLoading是有罪的:

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

在我原来的帖子forceLoad中总是被调用。它必须在else分支中。

于 2013-07-05T18:03:19.997 回答