【问题标题】:Loading SQLite data using AsyncTask , What am I doing wrong?使用 AsyncTask 加载 SQLite 数据,我做错了什么?
【发布时间】:2017-12-27 06:46:10
【问题描述】:

我是 android 和 java 的新手,我正在尝试实现一个异步加载器。但是没有数据被加载。我在这里在概念上遗漏了什么吗?

我的活动:

public class TestActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {


ListView bookList;
MyCursorAdapter myAdapter;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_admin_library);
  //  dloader = new DBLoader(this);
    //dloader.loadInBackground();

   /* blah blah*/

    getSupportLoaderManager().initLoader(1,null,this);

    /* blah blah*/
    View header = (View) getLayoutInflater().inflate(R.layout.row_layout_title, null);
    TextView totals = header.findViewById(R.id.mainText);
    totals.setText("Total Books: " + Integer.toString(totalBooks));
    bookList.addHeaderView(header);

    bookList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

            /* blah blah*/
            }


        }
    });
    /* blah blah*/
}

 /* blah blah*/

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
   /*CursorLoader loader = new CursorLoader(this, null, null, null, null, null){
        @Override
        public Cursor loadInBackground(){
            DBHandler db = new DBHandler(getContext());
            return db.getCursor();
        }
   };*/
   DBLoader loader  = new DBLoader(this);
    return loader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    myAdapter = new MyCursorAdapter(this,data,0);
    bookList.setAdapter(myAdapter);
    // myAdapter.swapCursor(data);
    //myAdapter.notifyDataSetChanged();
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    myAdapter.swapCursor(null);

}
}

DBLoader:

public class DBLoader extends AsyncTaskLoader<Cursor> {

private Cursor mCursor;
Context context;
public DBLoader(Context context) {
    super(context);
    this.context = context;
}

@Override
public Cursor loadInBackground() {
    DBHandler db = new DBHandler(context);
    Cursor cursor = db.getCursor();
    return cursor;
}

@Override
public void deliverResult(Cursor cursor){
    if(isReset()){
        releaseResources(cursor);
        return;
    }

    Cursor oldCursor = mCursor;
    mCursor = cursor;

    if(isStarted()){
        super.deliverResult(cursor);
    }

    if(oldCursor!=null && oldCursor!=cursor){
        releaseResources(oldCursor);
    }
}


private void releaseResources(Cursor cursor) {
    cursor.close();
}
}

我不知道我是否错过了这里的任何重要电话,互联网上的大多数资源都是关于内容提供商的(我不需要)。我只需要从本地 SQLite 数据库异步加载数据。

编辑:我的适配器:

public class MyCursorAdapter extends CursorAdapter {

private LayoutInflater cursorInflater;

public MyCursorAdapter(Context context, Cursor c, int flags) {
    super(context, c, flags);
    cursorInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {

    return cursorInflater.inflate(R.layout.row_layout, parent, false);
}

@Override
public void bindView(View v, Context context, Cursor cursor) {
    Log.d("Cursor :", cursor.getString(1));
    TextView title = (TextView) v.findViewById(R.id.listTitle);
    title.setText(cursor.getString(1));
    TextView author = (TextView) v.findViewById(R.id.listAuthor);
    author.setText(cursor.getString(2));
    TextView copies = (TextView) v.findViewById(R.id.listCopies);
    copies.setText(cursor.getString(5));

}

}

【问题讨论】:

  • 参见CursorLoader 来源 - 特别是onStartLoading
  • 添加你的 DBHandlerMyCursorAdapter
  • @OussemaAroua DBHandler 相当大。我已经使用 DBHandler 将光标放在 UI 线程上,它可以工作。 DBHandler.getCursor() 从数据库加载游标。我会上传适配器
  • 我已经使用适配器和dbhandler在UI线程中成功加载数据了。
  • 而不是MyCursorAdapter,只需使用SimpleCursorAdapter

标签: android android-asynctask android-sqlite loader


【解决方案1】:

将您的 DBLoader loader 声明为全局变量

onCreateLoader

loader  = new DBLoader(this);
return loader;

把它放在onCreate 方法而不是onLoadFinished

myAdapter = new MyCursorAdapter(this,null,0);
bookList.setAdapter(myAdapter);

把这个放在onLoadFinishied

this.loader=(DBLoader)loader;
adapter.changeCursor(cursor);

【讨论】:

  • 全局是指类变量,对吗?我将它作为一个普通的类变量和一个static 进行了尝试。两者都不起作用
  • 没有错误日志?尝试记录光标是否为空
  • 解决了它(不知何故?)。将.forceLoad() 添加到getSupportLoaderManager 就可以了。 (这可能会导致加载器在方向改变时重新加载......)
【解决方案2】:

经过一番搜索,我在互联网上看到了一些他们使用的示例 getSupportLoaderManager().initLoader(1,null,this).forceLoad();。这似乎行得通。在onCreateLoader() 中也调用loader.forceLoad() 也可以。在进一步检查中,我看到了这个:https://issuetracker.google.com/issues/36925900

看来我们必须在onStartLoading() 中实现forceLoad,如下所示:

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

这样做将不再需要在我们的活动中使用.forceLoad()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    相关资源
    最近更新 更多