2015-02-24 211 views
1

我正在嘗試學習Android開發。作爲一個學習項目,我正在創建一個「待辦事宜」應用程序。無法用sqlite數據庫中的數據填充列表視圖

我試圖來用我的表中的數據列表,這是我到目前爲止有:

ListCursorAdapter.java

package com.ryansmurphy.listado; 

import android.content.Context; 
import android.database.Cursor; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.TextView; 

/** 
* Created by ryanmurphy on 24/02/15. 
*/ 
public class ListCursorAdapter extends CursorAdapter { 

    public ListCursorAdapter(Context context, Cursor cursor) { 
     super(context, cursor, 0); 
    } 

    @Override 
    public View newView(Context context, Cursor cursor, ViewGroup parent) { 
     return LayoutInflater.from(context).inflate(R.layout.item_todo, parent, false); 
    } 

    public void bindView(View view, Context context, Cursor cursor) { 
     // Find fields to populate in inflated template 
     TextView todo = (TextView) view.findViewById(R.id.todoText); 
     // Extract properties from cursor 
     String todoTextDB = cursor.getString(cursor.getColumnIndexOrThrow("todo")); 
     // Populate fields with extracted properties 
     todo.setText(todoTextDB); 
    } 
} 

我收到兩條錯誤的位置:

  1. extends cursor。我收到錯誤Cannot resolve symbol
  2. super(context, cursor, 0);。我收到錯誤Object() in Object cannot be applied to

DatabaseHelper.java

package com.ryansmurphy.listado; 

import android.content.ContentValues; 
import android.content.Context; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 

/** 
* Created by ryanmurphy on 23/02/15. 
*/ 
public class DatabaseHelper extends SQLiteOpenHelper { 

    // Database Version 
    private static final int DATABASE_VERSION = 1; 

    // Database Name 
    private static final String DATABASE_NAME = "listado"; 

    // Table Name 
    private static final String TABLE_TODO = "todos"; 


    // Column names 
    private static final String KEY_ID = "id"; 
    private static final String KEY_TODO = "todo"; 
    private static final String KEY_STATUS = "status"; 
    private static final String KEY_CREATED_AT = "created_at"; 


    // Table Create Statements 
    // Todo table create statement 
    private static final String CREATE_TABLE_TODO = "CREATE TABLE " 
      + TABLE_TODO + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_TODO 
      + " TEXT," + KEY_STATUS + " INTEGER," + KEY_CREATED_AT 
      + " DATETIME" + ")"; 

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

    @Override 
    public void onCreate(SQLiteDatabase db) { 

     // creating required table 
     db.execSQL(CREATE_TABLE_TODO); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     // on upgrade drop older tables 
     db.execSQL("DROP TABLE IF EXISTS " + TABLE_TODO); 

     // create new tables 
     onCreate(db); 
    } 

    public void addRecord() 
    { 
     SQLiteDatabase database = getWritableDatabase(); 
     ContentValues values = new ContentValues(); 
     values.put("todo", "todo example"); 
     values.put("status", "not completed"); 
     database.insert("todos", null, values); 
     database.close(); 
    } 

    public Cursor getAll() 
    { 
     SQLiteDatabase database = getReadableDatabase(); 
     Cursor cursor = database.rawQuery("select * from todos",null); 
     return cursor; 
    } 
} 

現在我的列表視圖各行的xml: list_item.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" android:layout_height="match_parent"> 
    <TextView 
     android:id="@+id/todoText" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:textSize="24dp" 
     android:padding="6dp" /> 
</LinearLayout> 

ActivityMain.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" 
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> 
    <TextView android:text="To Do List" android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/title" /> 
    <ListView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/listview" 
     android:layout_below="@id/title" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentStart="true" 
     android:layout_marginTop="42dp" /> 
</RelativeLayout> 

MainActivity.Java

package com.ryansmurphy.listado; 

import android.content.Intent; 
import android.database.Cursor; 
import android.os.Bundle; 
import android.support.v7.app.ActionBarActivity; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.widget.ListView; 


public class MainActivity extends ActionBarActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     ListView lvItems = (ListView) findViewById(R.id.listview); 
     // Setup cursor adapter using cursor from last step 
     DatabaseHelper db = new DatabaseHelper(); 
     Cursor allRows = db.getAll(); 
     ListCursorAdapter todoAdapter = new ListCursorAdapter(this, allRows); 
     //Attach cursor adapter to the ListView 
     lvItems.setAdapter(todoAdapter); 
    } 

    @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_main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      return true; 
     } 

     if(id == R.id.addItem) 
     { 
      addItem(); 
     } 

     return super.onOptionsItemSelected(item); 
    } 

    public void addItem() 
    { 
     Intent addItemIntent= new Intent(MainActivity.this, AddItem.class); 
     startActivity(addItemIntent); 
    } 
} 

我正在這裏有兩個誤區:

  1. DatabaseHelper db = new DatabaseHelper();。我收到錯誤DatabaseHelper(Context) in DatabaseHelper cannot be applied
  2. lvItems.setAdapter(todoAdapter);。我收到錯誤setAdapter(android.widget.ListAdapter) in ListView cannot be applied

上面我已經從google搜索和試圖嘗試。我從來沒有真正知道我從一開始就一直在做什麼,但我慢慢地選擇了這一點,並且想知道如果你們在得到這些之後能夠幫助我。謝謝

+0

對於這行'DatabaseHelper db = new DatabaseHelper();'''MainActivity'',你應該傳遞'Context'對象。 'ActionBarActivity'是'Context'的一個子類,所以你可以將'this'作爲'Context'傳遞。 – 2015-02-24 16:13:17

回答

1

我將你的代碼複製到一個新的項目,並做了一些改動,使其工作。有一些區域我完全剝離 - 例如,getAll()方法,並用MainActivity中的查詢替換它。 Here是應用程序在第一次加載時的樣子,here是幾次點擊「添加」後的樣子。

對於它的價值,我認爲有更容易的方式來實現這一目標 - 例如,通過使用SimpleCursorAdapter,這將否定需要創建自己的自定義Adapter類,並讓您的MainActivity延長ListActivityListFragment。不過,我堅持使用你的方法。

我做了以下的微小變化,以DatabaseHelper,除了刪除getAll()方法:

@Override 
public void onCreate(SQLiteDatabase db) { 
    db.execSQL("CREATE TABLE todos (_id INTEGER PRIMARY KEY, todo TEXT, status INTEGER, created_at INTEGER);"); 
} 

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    Log.e(getClass().getSimpleName(), "onUpgrade: this is not required."); 
} 

我改變了漫長的級聯String CEATE_TABLE_TODO因爲我覺得這樣更易於閱讀。我還更改了列,以便它們包含文本和數字的組合。我還將onUpgrade()方法換成了簡單的錯誤消息,因爲我們在測試期間不應使用onUpgrade(),因爲只有在升級已發貨的應用程序時才需要此方法。

我對ListCursorAdapter做了一些小的修改,以便信息顯示一些有用的信息 - 在這種情況下,String位於cursor.getString(1)(這是第一列)。

public class ListCursorAdapter extends CursorAdapter { 

LayoutInflater inflater; 

public ListCursorAdapter(Context context, Cursor cursor) { 
    super(context, cursor, 0); 
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

@Override 
public View newView(Context context, Cursor cursor, ViewGroup parent) { 
    return inflater.inflate(R.layout.list_item, parent, false); 
} 

@Override 
public void bindView(View view, Context context, Cursor cursor) { 
    TextView todo = (TextView) view.findViewById(R.id.todoText); 
    String todoTextDB = cursor.getString(1); 
    todo.setText(todoTextDB); 
} 
} 

MainActivity,你DatabaseHelper需要context參數,這是我用this實現。 (你可以看到這一點,如果你回頭看看你的構造在DatabaseHelper

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

這且不說,我做的唯一的主要變化是對DatabaseHelperquery進入MainActivity,我把一個方法中調用runCursor()所以我們可以更新我們的ListView我們每次添加新項與addItem()

public class MainActivity extends ActionBarActivity { 

DatabaseHelper db; 
ListView lv; 
ListCursorAdapter adapter; 
Cursor allRows; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    db = new DatabaseHelper(this); 

    lv = (ListView) findViewById(R.id.list); 
    adapter = new ListCursorAdapter(this, runCursor()); 
    lv.setAdapter(adapter); 
} 

@Override 
public void onDestroy(){ 
    if (allRows != null) { 
     allRows.close(); 
    } 
    adapter.getCursor().close(); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.menu_main, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    int id = item.getItemId(); 
    if (id == R.id.action_settings) { 
     return true; 
    } 

    if(id == R.id.addItem) 
    { 
     addItem(); 
    } 

    return super.onOptionsItemSelected(item); 
} 

public void addItem() 
{ 
    db.addRecord(); 
    adapter.changeCursor(runCursor()); 
} 

Cursor runCursor() { 
    Cursor allRows = null; 
    allRows = db.getReadableDatabase().query(DatabaseHelper.TABLE_TODO, 
      new String[] {DatabaseHelper.KEY_ID, DatabaseHelper.KEY_TODO}, 
      null, null, null, null, null); 
    return allRows; 
    } 
} 

我還要提到的是我明確地通過重寫的onDestroy()關閉所有遊標對象,因爲他們可以容易出現內存泄漏。最後一個字太我沒有在這裏完成的是,最好將任何遊標查詢()移動到後臺線程,如AsyncTask。關於Android Developer pageCursor的更多信息,我建議!希望這是有用的!

+1

感謝您的出色答案。我用了很多你的改變,我希望你不要介意。但是,我接受了您的建議,並使用了simplecursoradapter及其更好。再次感謝 – RSM 2015-02-25 08:30:27

+0

很高興它是有用的! – PPartisan 2015-02-25 09:08:09