我的应用程序在3种不同的模拟器(api 16,21,24和25)上运行良好,但在真实设备上进行测试时仍会崩溃。我收到这些错误消息。但由于我是Android编程的新手,我真的不明白他们的意思。我正在使用RecycleView。调用的最后一个方法是onloadfinished方法,其中调用swapCursor方法。谢谢你的帮助。
09-18 23:41:30.699 8324-8324/com.a2sigma.workermanager E/CursorWindow:
Failed to read row 0, column 0 from a CursorWindow which has 0 rows, 45 columns.
09-18 23:41:30.706 8324-8324/com.a2sigma.workermanager D/AndroidRuntime: Shutting down VM
09-18 23:41:30.719 8324-8324/com.a2sigma.workermanager E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.a2sigma.workermanager, PID: 8324
java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetLong(Native Method)
at android.database.CursorWindow.getLong(CursorWindow.java:524)
at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)
at android.database.CursorWrapper.getLong(CursorWrapper.java:127)
at com.a2sigma.workermanager.CursorRecyclerViewAdapter.onBindViewHolder(CursorRecyclerViewAdapter.java:56)
at com.a2sigma.workermanager.CursorRecyclerViewAdapter.onBindViewHolder(CursorRecyclerViewAdapter.java:16)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6400)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6433)
at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5377)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5640)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5482)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5478)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2215)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1542)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1502)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:595)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3625)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3354)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3886)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1197)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.support.design.widget.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:131)
at android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42)
at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1389)
at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:868)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:18874)
09-18 23:41:30.720 8324-8324/com.a2sigma.workermanager E/AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:910)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2697)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2413)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1550)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7190)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:959)
at android.view.Choreographer.doCallbacks(Choreographer.java:734)
at android.view.Choreographer.doFrame(Choreographer.java:670)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:945)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
我的AdapterClass
package com.a2sigma.workermanager;
import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;
class CursorRecyclerViewAdapter extends
RecyclerView.Adapter<CursorRecyclerViewAdapter.WorkerViewHolder> {
private static final String TAG = "CursorRecyclerViewAdapt";
private Cursor mCursor;
private OnTaskClickListener mListener;
interface OnTaskClickListener {
void onEditClick(Worker worker);
void onDeleteClick(Worker worker);
void onWorkerClick(Worker worker);
}
CursorRecyclerViewAdapter(Cursor cursor, OnTaskClickListener listener) {
Log.d(TAG, "CursorRecyclerViewAdapter: Constructor called");
mCursor = cursor;
mListener = listener;
}
@Override
public WorkerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.d(TAG, "onCreateViewHolder: new view requested");
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.worker_list_items, parent,false);
return new WorkerViewHolder(view);
}
@Override
public void onBindViewHolder(WorkerViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: starts position " +position );
if((mCursor == null)||(mCursor.getCount() == 0)){
Log.d(TAG, "onBindViewHolder: providing instructions");
holder.name.setText(R.string.instructions_heading);
holder.noIndukKaryawan.setText(R.string.instructions);
holder.editButton.setVisibility(View.GONE);
holder.deleteButton.setVisibility(View.GONE);
}else {
if(!mCursor.moveToPosition(position)){
throw new IllegalStateException("Couldn't move cursor to position " +position);
}
Log.d(TAG, "onBindViewHolder: Hallooooooooo");
final Worker worker = new Worker(mCursor.getLong(mCursor.getColumnIndex(WorkersContract.Columns._ID)),
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.NAMA_KARYAWAN)),
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.JENIS_KELAMIN)),
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.TGL_LAHIR)),
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.TEMPAT_LAHIR)),
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.NKTP)),
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.NO_HP_1)),
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.NO_HP_2)),
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.NO_KK)),
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.IBU_KANDUNG)),
mCursor.getBlob(mCursor.getColumnIndex(WorkersContract.Columns.FOTO)));
Log.d(TAG, "onBindViewHolder: worker id "+ worker.getId());
holder.name.setText(worker.getmName());
holder.noIndukKaryawan.setText("NIK: " + worker.getmNIK());
holder.editButton.setVisibility(View.VISIBLE);//TODO add onClick listener
holder.deleteButton.setVisibility(View.VISIBLE); //TODO add onClick Listener
View.OnClickListener buttonListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "onClick: starts");
switch (view.getId()){
case R.id.wli_edit:
if(mListener != null){
mListener.onEditClick(worker);
}
break;
case R.id.wli_delete:
if(mListener!=null){
mListener.onDeleteClick(worker);
}
break;
default:
Log.d(TAG, "onClick: found unexpected button id");
}
}
};
holder.editButton.setOnClickListener(buttonListener);
holder.deleteButton.setOnClickListener(buttonListener);
}
}
@Override
public int getItemCount() {
Log.d(TAG, "getItemCount: starts");
if((mCursor == null) || (mCursor.getCount() == 0)){
return 1; // fib, because we populate a single viewHolder with instructions
}else {
return mCursor.getCount();
}
}
/**
* Swap in a new Cursor, returning the old Cursor.
* The returned old Cursor is <em>not</em> closed.
*
* @param newCursor The new cursor to be used
* @return Returns the previously set Cursor, or null if there wasn't one.
* If the given new Cursor is the same instance as the previously set
* Cursor, null is also returned.
*/
Cursor swapCursor(Cursor newCursor){
Log.d(TAG, "swapCursor: Called");
if(newCursor == mCursor){
return null;
}
final Cursor oldCursor = mCursor;
mCursor = newCursor;
if(newCursor !=null){
// notify the observers about the new cursor
notifyDataSetChanged();
}else {
// notify the obeservers about the lack of a data set
notifyItemRangeRemoved(0, getItemCount());
}
return oldCursor;
}
static class WorkerViewHolder extends RecyclerView.ViewHolder{
private static final String TAG = "TaskViewHolder";
TextView name = null;
TextView noIndukKaryawan = null;
ImageButton editButton = null;
ImageButton deleteButton = null;
public WorkerViewHolder(View itemView){
super(itemView);
Log.d(TAG, "TaskViewHolder: starts");
this.name = (TextView) itemView.findViewById(R.id.wli_name);
this.noIndukKaryawan = (TextView)itemView.findViewById(R.id.wli_nik);
this.editButton = (ImageButton) itemView.findViewById(R.id.wli_edit);
this.deleteButton = (ImageButton) itemView.findViewById(R.id.wli_delete);
}
}
}
XML文件 1. Worker_list_items
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/wli_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="16dp"
android:textColor="?android:attr/textColorPrimary"
android:textSize="22sp"
android:textStyle="bold"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/wli_edit"
app:layout_constraintTop_toTopOf="parent"
tools:text="Nama Karyawan" />
<TextView
android:id="@+id/wli_nik"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="1dp"
android:textColor="?android:attr/textColorSecondary"
android:textSize="18sp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/wli_edit"
app:layout_constraintTop_toBottomOf="@+id/wli_name"
tools:text="123.256.478" />
<ImageButton
android:id="@+id/wli_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="16dp"
android:contentDescription="@string/delete_button"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/ic_menu_delete" />
<ImageButton
android:id="@+id/wli_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="0dp"
android:contentDescription="@string/edit_button"
app:layout_constraintRight_toLeftOf="@+id/wli_delete"
app:layout_constraintTop_toTopOf="@+id/wli_delete"
app:srcCompat="@android:drawable/ic_menu_edit" />
</android.support.constraint.ConstraintLayout>
和RycycleView XML文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/worker_list"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp" />
</android.support.constraint.ConstraintLayout>
答案 0 :(得分:0)
通常是通胀错误。您需要比较您尝试填充的视图ID,确保它们不为空,并且您正确使用Recycler View Holder Adapter进行设置。
发布您的适配器,您正在填充的行的xml,您的查看器模式以及您的适配器设置和分配,我们当然可以让您平方。
只需更新答案,您的光标应该在访问之前正确填充,并且您应该在访问之前确保内容存在。
填充Cursor的示例
Cursor cursor = null;
try {
cursor = queryBuilder.query(MySQLDBHelper.openDatabase(<YOUR CONTEXT>), projection, selection, selectionArgs, null, null, sortOrder);
} catch (Exception e) {
e.printStackTrace();
}
return cursor;
接下来,当您决定从光标访问值时,您可以进行一些安全检查,而不是直接访问它们。它可能会变得相当冗长所以我建议创建一个从游标创建对象的方法,然后在那里进行所有空的安全检查。
而不是:
mCursor.getString(mCursor.getColumnIndex(WorkersContract.Columns.IBU_KANDUNG)));
做类似的事情:
int IBU_KANDUNG_INDEX = mCursor.getColumnIndex(WorkersContract.Columns.IBU_KANDUNG);
myObject.setString(mCursor.getString(IBU_KANDUNG_INDEX) == null ? "" : mCursor.getString(IBU_KANDUNG_INDEX));
这将确保您不会将空值设置到对象中或尝试访问空的游标的-1索引。