在从游标访问数据之前,请确保已正确初始化游标。如何解决它?

时间:2018-09-17 21:54:33

标签: java android sqlite

我想在活动中的片段中显示我从SQLite DB到RecyclerView的数据。 iget错误行:contactList.add(m);在Databese助手getAllUsers方法中。

这是我的logcat:

09-17 18:11:17.487 2101-2101/ir.shirazmetro E/CursorWindow: Failed to read row 0, column 1 from a CursorWindow which has 17 rows, 1 columns.
09-17 18:11:17.487 2101-2101/ir.shirazmetro D/AndroidRuntime: Shutting down VM


    --------- beginning of crash
09-17 18:11:17.487 2101-2101/ir.shirazmetro E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ir.shirazmetro, PID: 2101
    java.lang.IllegalStateException: Couldn't read row 0, col 1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
        at android.database.CursorWindow.nativeGetString(Native Method)
        at android.database.CursorWindow.getString(CursorWindow.java:438)
        at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
        at ir.shirazmetro.DatabaseHelper.getAllUsers(DatabaseHelper.java:89)
        at ir.shirazmetro.views.fragments.toDastgheybFragment.onActivityCreated(toDastgheybFragment.java:58)
        at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:2344)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1446)
        at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1754)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1822)
        at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
        at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2591)
        at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2378)
        at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2333)
        at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2210)
        at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:649)
        at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:145)
        at android.support.v4.view.ViewPager.populate(ViewPager.java:1239)
        at android.support.v4.view.ViewPager.populate(ViewPager.java:1087)
        at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1617)
        at android.view.View.measure(View.java:17547)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:875)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
        at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2615)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2015)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1173)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1379)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
        at android.view.Choreographer.doCallbacks(Choreographer.java:580)
        at android.view.Choreographer.doFrame(Choreographer.java:550)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Cho

这是我的代码:

Activity.java:

public class station extends BaseActivity {
    Toolbar mToolbar;
    private TabLayout tbLayout;
    private ViewPager vPager;
    private ButtonCell backBtn;
    Boolean btnOneOn = false;
    Boolean btnTwoOn = false;
    Boolean btnThreeOn = false;
    Boolean btnfourOn = false;
    ButtonCell Button2;
    ButtonCell Button1;
    ButtonCell Button3;
    ButtonCell Button4;

    private List<DatabaseModel> LineList = new ArrayList<>();
    private RecyclerView recyclerView;
    private DataAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_station);

        mToolbar = findViewById(R.id.tlbr1);
        setSupportActionBar(mToolbar);

        DatabaseHelper helpher;
        helpher = new DatabaseHelper(station.this);
        helpher.insertIntoDB("dastgheyb", "06:10:00", "B");
        helpher.close();
        initView();
        setupWithViewPager();
        tbLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }
}

这是DataAdapter.java:

public class DataAdapter extends RecyclerView.Adapter<DataAdapter.MyViewHolder> {
    private List<DatabaseModel> LineList;
    public Context mContext;

    public DataAdapter(Context mContext, List<DatabaseModel> line1List) {
        this.LineList = line1List;
        this.mContext = mContext;
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {
        TextViewCell Time;

        public MyViewHolder(View view) {
            super(view);
            //initialize textViews and buttons
            Time = view.findViewById(R.id.textView);
        }
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //set item layout using layout inflater
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_to_dastgheyb, parent, false);
        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        final DatabaseModel list = LineList.get(position);
        holder.Time.setText(list.getTime());
    }

    @Override
    public int getItemCount() {
        return LineList.size();
    }
}

这是我的fragment.java:

public class toDastgheybFragment extends BaseFragment {
    private Activity mActivity = null;
    private View mView;
    private RecyclerFragmentListener mFragmentListener = null;

    // RecyclerViewとAdapter
    private RecyclerView mRecyclerView;
    DataAdapter mAdapter;

    public interface RecyclerFragmentListener {
        void onRecyclerEvent();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_to_dastgheyb, container, false);
        mRecyclerView = mView.findViewById(R.id.myRecycler);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
        return mView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        Cursor cursor;
        List<DatabaseModel> LineList = new ArrayList<>();
        LineList.clear();
        DatabaseHelper db = new DatabaseHelper(getContext());
        //data from database is returned to m
        final List<DatabaseModel> m = db.getAllUsers();
        Log.w("SIZe", "" + m.size());
        //if m contains data
        if (m.size() > 0) {
            //loop through contents
            for (int i = 0; i < m.size(); i++) {
                Log.w("NAME", m.get(i).getTime());
                //add data to list used in adapter
                LineList.add(m.get(i));
                //notify data change
                mAdapter.notifyDataSetChanged();
            }
        }

        db.close();

        mAdapter = new DataAdapter(mActivity, LineList);
        mRecyclerView.setAdapter(mAdapter);
    }

    public void onRecyclerClicked(View v, int position) {

    }
}

这是我的DataHelper.java:

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "MetroDB";//name of the database
    private static final String TABLE_NAME = "stationtime";//name for the table

    private static final String Station = "station";
    private static final String Time = "time";
    private static final String Line = "line";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        //Query to create table in databse
        String CREATE_CONTACTS_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" + Station + " TEXT," + Time + " TEXT," + Line + " TEXT);";
        db.execSQL(CREATE_CONTACTS_TABLE);
    }

    //Executes once a database change is occurred
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }

    //method to add row to table
    void addToLine1(DatabaseModel m) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        values.put(Station, m.getStation());

        values.put(Time, m.getTime());

        values.put(Line, m.getLine());


        db.insert(TABLE_NAME, null, values);
        db.close();
    }

    public void insertIntoDB(String station,String time,String line) {
        // 1. get reference to writable DB
        SQLiteDatabase db1 = this.getWritableDatabase();

        // 2. create ContentValues to add key "column"/value
        ContentValues values = new ContentValues();
        values.put("station", station);
        values.put("time", time);
        values.put("line", line);

        // 3. insert
        db1.insert(TABLE_NAME, null, values);
        // 4. close
        db1.close();
    }

    //method to list all details from table
    public List<DatabaseModel> getAllUsers() {
        List<DatabaseModel> contactList = new ArrayList<DatabaseModel>();
        String selectQuery = "SELECT " + Time + " FROM " + TABLE_NAME + ";";//retrieve data from the database
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        cursor.moveToFirst();
        if (cursor.getCount()>0) {
            do {
                DatabaseModel m = new DatabaseModel();
                //                m.setStation(cursor.getString(0));
                m.setTime(cursor.getString(1));
                //              m.setLine(cursor.getString(2));
                contactList.add(m);
            } while (cursor.moveToNext());
        }
        return contactList;
    }
}

以及DatabaseModel.java:

public class DatabaseModel {
    String station, time, line;

    public DatabaseModel() {
    }

    public DatabaseModel(String station, String time, String line) {
        this.station = station;
        this.time = time;
        this.line = line;
    }

    public String getStation() {
        return station;
    }

    public void setStation(String station) {
        this.station = station;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getLine() {
        return line;
    }

    public void setLine(String line) {
        this.line = line;
    }
}

2 个答案:

答案 0 :(得分:0)

  

无法从具有17行的CursorWindow中读取第0行第1列,   1列。

我认为您遇到的问题实际上是第DatabaseHelper.java行,第89行,我猜应该是m.setTime(cursor.getString(1));

具体来说,失败的部分应该是cursor.getString(1)

您正在运行的查询只有一列,其索引应为0而不是1。

有一种更简单的方法可以避免这种麻烦。您可以按名称访问列。

cursor.getString(cursor.getColumnIndex(String columnName));

由于Time拥有time字段的名称,在这种情况下为:

cursor.getString(cursor.getColumnIndex(Time));

您在此处输入Time作为列名,它应该返回正确的列。

问题2

  

将错误更改为:java.lang.NullPointerException:尝试调用   虚方法   ir.shirazmetro.views.adapters.DataAdapter.notifyDataSetChanged()'   空对象引用

在运行查询并调用Fragment之后,在mAdapter中检入mAdapter.notifyDataSetChanged();的初始化在方法的底部。

这就是为什么您获得NPE的原因。如果在该行上放置一个断点,则会看到mAdapter为空。

如果可能,请使用mAdapter = new DataAdapter(mActivity, LineList);的{​​{1}}方法初始化适配器(Fragment)。

您可以调用onCreate()的{​​{1}}来代替传递mActivity

以我认为从未设置Fragment的方式。 getActivity();对于活动可能很棘手。我将删除该引用,并始终依赖于在片段中调用mActivity

答案 1 :(得分:-1)

使用rawQuery时, SQL字符串不能为;终止,但在您的代码中:

String selectQuery = "SELECT " + Time + " FROM " + TABLE_NAME + ";"; 

应为:

String selectQuery = "SELECT " + Time + " FROM " + TABLE_NAME;