由于带有 cursorloader 的 recyclerview,空白主 activity
Blank main activity due to recyclerview with a cursorloader
现在我正在尝试将 recyclerview 与游标加载器一起使用。根据我的研究,我将 cursorloader 包含在我的 recyclerview 适配器中。我不想将我的 SQLite 数据库数据放入数组列表中。现在看起来我的代码是正确的,但是当我加载应用程序时,我得到一个空白屏幕。谁能帮我看看我的代码中的错误?
这是我的适配器:
public class PrescriptionRecyclerAdapter extends RecyclerView.Adapter<PrescriptionRecyclerAdapter.ViewHolder> {
private CursorAdapter mCursorAdapter;
private Context mContext;
private ViewHolder holder;
Cursor prescriptionCursor;
public PrescriptionRecyclerAdapter(Context context, Cursor c) {
mContext = context;
prescriptionCursor = c;
mCursorAdapter = new CursorAdapter(mContext, c, 0) {
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// Inflate the view here
View v = LayoutInflater.from(context)
.inflate(R.layout.recycle_item, parent, false);
return v;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
// Extract data from the current store row and column
int nameColumnIndex = cursor.getColumnIndex(PrescriptionContract.PrescriptionEntry.COLUMN_PRESCRIPTION_NAME);
int amountColumnIndex = cursor.getColumnIndex(PrescriptionContract.PrescriptionEntry.COLUMN_PRESCRIPTION_AMOUNT);
int durationColumnIndex = cursor.getColumnIndex(PrescriptionContract.PrescriptionEntry.COLUMN_PRESCRIPTION_FREQUENCY_DURATION);
final int columnIdIndex = cursor.getColumnIndex(PrescriptionContract.PrescriptionEntry._ID);
//Read the store attritubes from the Cursor for the current stores
String name = cursor.getString(nameColumnIndex);
String amount = cursor.getString(amountColumnIndex);
String duration = cursor.getString(durationColumnIndex);
String col = cursor.getString(columnIdIndex);
// Populate fields with extracted properties
holder.prescriptionName.setText(name);
holder.prescriptionAmount.setText(amount);
holder.prescriptionDays.setText(duration);
}
};
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView prescriptionName;
public TextView prescriptionAmount;
public TextView prescriptionDays;
final public Button prescriptionButton;
public ViewHolder(View itemView) {
super(itemView);
// Find fields to populate in inflated template
prescriptionName = (TextView) itemView.findViewById(R.id.name);
prescriptionAmount = (TextView) itemView.findViewById(R.id.amountlist);
prescriptionDays = (TextView) itemView.findViewById(R.id.daysList);
prescriptionButton = itemView.findViewById(R.id.scheduleButton);
}
}
@Override
public int getItemCount() {
return mCursorAdapter.getCount();
}
public Cursor swapCursor(Cursor cursor) {
if (prescriptionCursor == cursor) {
return null;
}
Cursor oldCursor = prescriptionCursor;
this.prescriptionCursor = cursor;
if (cursor != null) {
this.notifyDataSetChanged();
}
return oldCursor;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Passing the binding operation to cursor loader
mCursorAdapter.getCursor().moveToPosition(position);
mCursorAdapter.bindView(holder.itemView, mContext, mCursorAdapter.getCursor());
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Passing the inflater job to the cursor-adapter
View v = mCursorAdapter.newView(mContext, mCursorAdapter.getCursor(), parent);
holder = new ViewHolder(v);
return holder;
}
}
这是我的展示activity。
public class DisplayActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
private static final int PRESCRIPTION_LOADER = 0;
PrescriptionRecyclerAdapter mCursorAdapter;
private RecyclerView.LayoutManager mLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(DisplayActivity.this, EditorActivity.class);
startActivity(intent);
}
});
RecyclerView prescriptionRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mLayoutManager = new LinearLayoutManager(getApplicationContext());
prescriptionRecyclerView.setLayoutManager(mLayoutManager);
mCursorAdapter = new PrescriptionRecyclerAdapter(this, null);
prescriptionRecyclerView.setAdapter(mCursorAdapter);
//Kick off the loader
getLoaderManager().initLoader(PRESCRIPTION_LOADER,null,this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_display, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// User clicked on a menu option in the app bar overflow menu
switch (item.getItemId()) {
// Respond to a click on the "Delete all entries" menu option
case R.id.action_delete_all_entries:
deleteAllPrescriptions();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Helper method to delete all items in the database.
*/
private void deleteAllPrescriptions() {
int rowsDeleted = getContentResolver().delete(PrescriptionEntry.CONTENT_URI, null, null);
Log.v("CatalogActivity", rowsDeleted + " rows deleted from prescription database");
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
// Since the editor shows all store attributes, define a projection that contains
// all columns from the store table
String[] projection = {
PrescriptionEntry._ID,
PrescriptionEntry.COLUMN_PRESCRIPTION_NAME,
PrescriptionEntry.COLUMN_PRESCRIPTION_AMOUNT,
PrescriptionEntry.COLUMN_PRESCRIPTION_FREQUENCY_HOURS,
PrescriptionEntry.COLUMN_PRESCRIPTION_FREQUENCY_TIMES,
PrescriptionEntry.COLUMN_PRESCRIPTION_FREQUENCY_DURATION,
PrescriptionEntry.COLUMN_PRESCRIPTION_REFILL,
PrescriptionEntry.COLUMN_PRESCRIPTION_EXPIRATION,
PrescriptionEntry.COLUMN_PRESCRIPTION_PHARMACIST_NAME,
PrescriptionEntry.COLUMN_PRESCRIPTION_PHARMACIST_NUMBER,
PrescriptionEntry.COLUMN_PRESCRIPTION_PHYSICIAN_NAME,
PrescriptionEntry.COLUMN_PRESCRIPTION_PHYSICIAN_NUMBER};
// This loader will execute the ContentProvider's query method on a background thread
return new CursorLoader(this, // Parent activity context
PrescriptionEntry.CONTENT_URI, // Query the content URI for the current store
projection, // Columns to include in the resulting Cursor
null, // No selection clause
null, // No selection arguments
null); // Default sort order
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mCursorAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mCursorAdapter.swapCursor(null);
}
}
我想我明白了你的问题。在 onLoadFinished
方法中获得新的 Cursor
后,您正在调用 PrescriptionRecyclerAdapter
的 swapCursor()
方法,此方法正在更新 prescriptionCursor
游标引用。没关系。但是更新 prescriptionCursor
不会影响您的 CursorAdapter
。你实际上依赖于CursorAdapter
。所以你必须更新 CursorAdapter
的 Cursor
。因为您的 mCursorAdapter
仍然持有您在构造函数中提供的 Cursor
的旧引用。
所以使用这个方法来更新游标引用mCursorAdapter.swapCursor(prescriptionCursor)
。
public Cursor swapCursor(Cursor cursor) {
if (prescriptionCursor == cursor) {
return null;
}
Cursor oldCursor = prescriptionCursor;
this.prescriptionCursor = cursor;
if (cursor != null) {
this.notifyDataSetChanged();
// update your Cursor for CursorAdapter
mCursorAdapter.swapCursor(prescriptionCursor);
}
return oldCursor;
}
我认为您通过维护两个适配器使其变得复杂。您可以将 RecyclerView.Adapter
与 List
或 Cursor
一起使用。没有必要让它变得复杂。
希望对您有所帮助。让我知道它可以解决您的问题。
现在我正在尝试将 recyclerview 与游标加载器一起使用。根据我的研究,我将 cursorloader 包含在我的 recyclerview 适配器中。我不想将我的 SQLite 数据库数据放入数组列表中。现在看起来我的代码是正确的,但是当我加载应用程序时,我得到一个空白屏幕。谁能帮我看看我的代码中的错误?
这是我的适配器:
public class PrescriptionRecyclerAdapter extends RecyclerView.Adapter<PrescriptionRecyclerAdapter.ViewHolder> {
private CursorAdapter mCursorAdapter;
private Context mContext;
private ViewHolder holder;
Cursor prescriptionCursor;
public PrescriptionRecyclerAdapter(Context context, Cursor c) {
mContext = context;
prescriptionCursor = c;
mCursorAdapter = new CursorAdapter(mContext, c, 0) {
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// Inflate the view here
View v = LayoutInflater.from(context)
.inflate(R.layout.recycle_item, parent, false);
return v;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
// Extract data from the current store row and column
int nameColumnIndex = cursor.getColumnIndex(PrescriptionContract.PrescriptionEntry.COLUMN_PRESCRIPTION_NAME);
int amountColumnIndex = cursor.getColumnIndex(PrescriptionContract.PrescriptionEntry.COLUMN_PRESCRIPTION_AMOUNT);
int durationColumnIndex = cursor.getColumnIndex(PrescriptionContract.PrescriptionEntry.COLUMN_PRESCRIPTION_FREQUENCY_DURATION);
final int columnIdIndex = cursor.getColumnIndex(PrescriptionContract.PrescriptionEntry._ID);
//Read the store attritubes from the Cursor for the current stores
String name = cursor.getString(nameColumnIndex);
String amount = cursor.getString(amountColumnIndex);
String duration = cursor.getString(durationColumnIndex);
String col = cursor.getString(columnIdIndex);
// Populate fields with extracted properties
holder.prescriptionName.setText(name);
holder.prescriptionAmount.setText(amount);
holder.prescriptionDays.setText(duration);
}
};
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView prescriptionName;
public TextView prescriptionAmount;
public TextView prescriptionDays;
final public Button prescriptionButton;
public ViewHolder(View itemView) {
super(itemView);
// Find fields to populate in inflated template
prescriptionName = (TextView) itemView.findViewById(R.id.name);
prescriptionAmount = (TextView) itemView.findViewById(R.id.amountlist);
prescriptionDays = (TextView) itemView.findViewById(R.id.daysList);
prescriptionButton = itemView.findViewById(R.id.scheduleButton);
}
}
@Override
public int getItemCount() {
return mCursorAdapter.getCount();
}
public Cursor swapCursor(Cursor cursor) {
if (prescriptionCursor == cursor) {
return null;
}
Cursor oldCursor = prescriptionCursor;
this.prescriptionCursor = cursor;
if (cursor != null) {
this.notifyDataSetChanged();
}
return oldCursor;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Passing the binding operation to cursor loader
mCursorAdapter.getCursor().moveToPosition(position);
mCursorAdapter.bindView(holder.itemView, mContext, mCursorAdapter.getCursor());
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Passing the inflater job to the cursor-adapter
View v = mCursorAdapter.newView(mContext, mCursorAdapter.getCursor(), parent);
holder = new ViewHolder(v);
return holder;
}
}
这是我的展示activity。
public class DisplayActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
private static final int PRESCRIPTION_LOADER = 0;
PrescriptionRecyclerAdapter mCursorAdapter;
private RecyclerView.LayoutManager mLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(DisplayActivity.this, EditorActivity.class);
startActivity(intent);
}
});
RecyclerView prescriptionRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mLayoutManager = new LinearLayoutManager(getApplicationContext());
prescriptionRecyclerView.setLayoutManager(mLayoutManager);
mCursorAdapter = new PrescriptionRecyclerAdapter(this, null);
prescriptionRecyclerView.setAdapter(mCursorAdapter);
//Kick off the loader
getLoaderManager().initLoader(PRESCRIPTION_LOADER,null,this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_display, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// User clicked on a menu option in the app bar overflow menu
switch (item.getItemId()) {
// Respond to a click on the "Delete all entries" menu option
case R.id.action_delete_all_entries:
deleteAllPrescriptions();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Helper method to delete all items in the database.
*/
private void deleteAllPrescriptions() {
int rowsDeleted = getContentResolver().delete(PrescriptionEntry.CONTENT_URI, null, null);
Log.v("CatalogActivity", rowsDeleted + " rows deleted from prescription database");
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
// Since the editor shows all store attributes, define a projection that contains
// all columns from the store table
String[] projection = {
PrescriptionEntry._ID,
PrescriptionEntry.COLUMN_PRESCRIPTION_NAME,
PrescriptionEntry.COLUMN_PRESCRIPTION_AMOUNT,
PrescriptionEntry.COLUMN_PRESCRIPTION_FREQUENCY_HOURS,
PrescriptionEntry.COLUMN_PRESCRIPTION_FREQUENCY_TIMES,
PrescriptionEntry.COLUMN_PRESCRIPTION_FREQUENCY_DURATION,
PrescriptionEntry.COLUMN_PRESCRIPTION_REFILL,
PrescriptionEntry.COLUMN_PRESCRIPTION_EXPIRATION,
PrescriptionEntry.COLUMN_PRESCRIPTION_PHARMACIST_NAME,
PrescriptionEntry.COLUMN_PRESCRIPTION_PHARMACIST_NUMBER,
PrescriptionEntry.COLUMN_PRESCRIPTION_PHYSICIAN_NAME,
PrescriptionEntry.COLUMN_PRESCRIPTION_PHYSICIAN_NUMBER};
// This loader will execute the ContentProvider's query method on a background thread
return new CursorLoader(this, // Parent activity context
PrescriptionEntry.CONTENT_URI, // Query the content URI for the current store
projection, // Columns to include in the resulting Cursor
null, // No selection clause
null, // No selection arguments
null); // Default sort order
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mCursorAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mCursorAdapter.swapCursor(null);
}
}
我想我明白了你的问题。在 onLoadFinished
方法中获得新的 Cursor
后,您正在调用 PrescriptionRecyclerAdapter
的 swapCursor()
方法,此方法正在更新 prescriptionCursor
游标引用。没关系。但是更新 prescriptionCursor
不会影响您的 CursorAdapter
。你实际上依赖于CursorAdapter
。所以你必须更新 CursorAdapter
的 Cursor
。因为您的 mCursorAdapter
仍然持有您在构造函数中提供的 Cursor
的旧引用。
所以使用这个方法来更新游标引用mCursorAdapter.swapCursor(prescriptionCursor)
。
public Cursor swapCursor(Cursor cursor) {
if (prescriptionCursor == cursor) {
return null;
}
Cursor oldCursor = prescriptionCursor;
this.prescriptionCursor = cursor;
if (cursor != null) {
this.notifyDataSetChanged();
// update your Cursor for CursorAdapter
mCursorAdapter.swapCursor(prescriptionCursor);
}
return oldCursor;
}
我认为您通过维护两个适配器使其变得复杂。您可以将 RecyclerView.Adapter
与 List
或 Cursor
一起使用。没有必要让它变得复杂。
希望对您有所帮助。让我知道它可以解决您的问题。