Android从数据库中提取数据

时间:2013-05-16 21:18:53

标签: android

我试图为数据库提取历史记录....但它从不拉扯任何东西......任何人都能看到我做错了什么

以下是内容提供商:

package com.projectcaruso.naturalfamilyplaning;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;

public class StatusProvider extends ContentProvider {
  private static final String TAG = StatusProvider.class.getSimpleName();

  public static final Uri CONTENT_URI = Uri.parse("content://com.projectcaruso.naturalfamilyplaning.statusprovider");
  public static final String SINGLE_RECORD_MIME_TYPE = "vnd.android.cursor.item/vnd.projectcaruso.naturalfamilyplaning.status";
  public static final String MULTIPLE_RECORDS_MIME_TYPE = "vnd.android.cursor.dir/vnd.projectcaruso.naturalfamilyplaning.status";

  StatusData statusData;

  @Override
  public String getType(Uri uri) {
    return this.getId(uri) < 0 ? MULTIPLE_RECORDS_MIME_TYPE
        : SINGLE_RECORD_MIME_TYPE;
  }

  @Override
  public boolean onCreate() {
    statusData = new StatusData(getContext());
    return true;
  }

  @Override
  public Uri insert(Uri uri, ContentValues values) {
    SQLiteDatabase db = statusData.dbHelper.getWritableDatabase();
    try {
      long id = db.insertOrThrow(StatusData.DATABASE_TABLE, null, values);
      if (id == -1) {
        throw new RuntimeException(String.format(
            "%s: Failed to insert [%s] to [%s] for unknown reasons.", TAG,
            values, uri));
      } else {
        Uri newUri = ContentUris.withAppendedId(uri, id);
        // Notify the Context's ContentResolver of the change
        getContext().getContentResolver().notifyChange(newUri, null);
        return newUri;
      }
    } finally {
      db.close();
    }
  }

  @Override
  public int update(Uri uri, ContentValues values, String selection,
      String[] selectionArgs) {
    long id = this.getId(uri);
    int count;
    SQLiteDatabase db = statusData.dbHelper.getWritableDatabase();
    try {
      if (id < 0) {
        count = db.update(StatusData.DATABASE_TABLE, values, selection, selectionArgs);
      } else {
        count = db.update(StatusData.DATABASE_TABLE, values, StatusData.KEY_ROWID + "=" + id,
            null);
      }
    } finally {
      db.close();
    }

    // Notify the Context's ContentResolver of the change
    getContext().getContentResolver().notifyChange(uri, null);

    return count;
  }

  @Override
  public int delete(Uri uri, String selection, String[] selectionArgs) {
    long id = this.getId(uri);
    int count;
    SQLiteDatabase db = statusData.dbHelper.getWritableDatabase();
    try {
      if (id < 0) {
        count = db.delete(StatusData.DATABASE_TABLE, selection, selectionArgs);
      } else {
        count = db.delete(StatusData.DATABASE_TABLE, StatusData.KEY_ROWID + "=" + id, null);
      }
    } finally {
      db.close();
    }

    // Notify the Context's ContentResolver of the change
    getContext().getContentResolver().notifyChange(uri, null);

    return count;
  }

  @Override
  public Cursor query(Uri uri, String[] projection, String selection,
      String[] selectionArgs, String sortOrder) {
    long id = this.getId(uri);
    SQLiteDatabase db = statusData.dbHelper.getReadableDatabase();
    Log.d(TAG, "querying");

    Cursor c;

    if (id < 0) {
      c = db.query(StatusData.DATABASE_TABLE, projection, selection, selectionArgs,
          null, null, sortOrder);
    } else {
      c = db.query(StatusData.DATABASE_TABLE, projection, StatusData.KEY_ROWID + "=" + id,
          null, null, null, null);
    }

    // Notify the context's ContentResolver if the cursor result set changes
    c.setNotificationUri(getContext().getContentResolver(), uri);

    return c;
  }

  // Helper method to extract ID from Uri
  private long getId(Uri uri) {
    String lastPathSegment = uri.getLastPathSegment();
    if (lastPathSegment != null) {
      try {
        return Long.parseLong(lastPathSegment);
      } catch (NumberFormatException e) {
        // at least we tried
      }
    }
    return -1;
  }
}

历史片段:

    package com.projectcaruso.naturalfamilyplaning;

    import com.projectcaruso.naturalfamilyplanning.R;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.database.Cursor;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.text.format.DateUtils;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ListView;
    import android.widget.SimpleCursorAdapter;
    import android.widget.TextView;
    import android.widget.SimpleCursorAdapter.ViewBinder;


    public class HistoryFragment extends Fragment {
      static final String SEND_TIMELINE_NOTIFICATIONS = "com.marakana.yamba.SEND_TIMELINE_NOTIFICATIONS";

      Cursor cursor;
      ListView listTimeline;
      SimpleCursorAdapter adapter;
      static final String[] FROM = { StatusData.KEY_CHARTING_DATE, StatusData.KEY_NAME, StatusData.KEY_CHARTING_NOTES };
      static final int[] TO = { R.id.textCreatedAt, R.id.textUser, R.id.textText };
      TimelineReceiver receiver;
      IntentFilter filter;

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

      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

          View view = inflater.inflate(R.layout.fragment_history, container, false);
          listTimeline = (ListView) view.findViewById(R.id.listTimeline);

         // Create the receiver
         //receiver = new TimelineReceiver();
         //filter = new IntentFilter( UpdaterService.NEW_STATUS_INTENT );

        return view;
      }

      @Override
      public void onResume() {
        super.onResume();

        this.setupList();

        // Register the receiver
        //super.registerReceiver(receiver, filter,
        //    SEND_TIMELINE_NOTIFICATIONS, null);
      }

      @Override
      public void onPause() {
        super.onPause();

        // UNregister the receiver
        //unregisterReceiver(receiver);
      }

      // Responsible for fetching data and setting up the list and the adapter
      private void setupList() { // <5>
        // Get the data
        Cursor c = getActivity().getContentResolver().query(StatusProvider.CONTENT_URI, null, null, null, StatusData.KEY_CHARTING_DATE + " DESC"); // <3>
        getActivity().startManagingCursor(cursor);

        // Setup Adapter
        adapter = new SimpleCursorAdapter(getActivity(), R.layout.row, cursor, FROM, TO);
        adapter.setViewBinder(VIEW_BINDER); // <6>
        listTimeline.setAdapter(adapter);
      }

      // View binder constant to inject business logic for timestamp to relative
      // time conversion
      static final ViewBinder VIEW_BINDER = new ViewBinder() {

        public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
          if(view.getId() != R.id.textCreatedAt) return false;

          // Update the created at text to relative time
          long timestamp = cursor.getLong(columnIndex);
          CharSequence relTime = DateUtils.getRelativeTimeSpanString(view.getContext(), timestamp);
          ((TextView)view).setText(relTime);

          return true;
        }
      };

      // Receiver to wake up when UpdaterService gets a new status
      // It refreshes the timeline list by requerying the cursor
      class TimelineReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
          setupList();
          Log.d("TimelineReceiver", "onReceived");
        }
      }
    }

片段历史记录:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:orientation ="vertical"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent" >

        <!-- Title -->
         <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:gravity="center"
             android:layout_margin="10dp"
             android:text="@string/title_history"
             android:textColor="#fff"
             android:textSize="30sp" />

        <ListView
             android:layout_width="fill_parent"
             android:layout_height="fill_parent"
             android:id="@+id/listTimeline" />

    </LinearLayout>

历史排:

<?xml version="1.0" encoding="utf-8"?>
  <!-- <1> -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_height="wrap_content" android:orientation="vertical"
  android:layout_width="fill_parent">

  <!-- <2> -->
  <LinearLayout android:layout_height="wrap_content"
    android:layout_width="fill_parent">

    <!-- <3> -->
    <TextView android:layout_height="wrap_content"
      android:layout_width="fill_parent" android:layout_weight="1"
      android:id="@+id/textUser" android:text="Slashdot"
      android:textStyle="bold" />

    <!-- <4> -->
    <TextView android:layout_height="wrap_content"
      android:layout_width="fill_parent" android:layout_weight="1"
      android:gravity="right" android:id="@+id/textCreatedAt"
      android:text="10 minutes ago" />
  </LinearLayout>

  <!-- <5> -->
  <TextView android:layout_height="wrap_content"
    android:layout_width="fill_parent" android:id="@+id/textText"
    android:text="Firefox comes to Android" />


</LinearLayout>

数据库:

public class StatusData {

    //Database information
    private static final String DATABASE_NAME = "NFP";
    private static final int DATABASE_VERSION = 1;

    //Table Information
    static final String DATABASE_TABLE = "charting";
    public static final String KEY_ROWID = "_id";
    public static final String KEY_NAME = "username";
    public static final String KEY_CHARTING_DATE = "Date";
    public static final String KEY_CHARTING_TEMPERATURE = "temperature";
    public static final String KEY_CHARTING_STAMPS = "Stamps";
    public static final String KEY_CHARTING_FERTILE = "Fertile";
    public static final String KEY_CHARTING_NOTES = "Notes";
    public static final String KEY_CHARTING_PROC = "Proc";

    private static final String GET_ALL_ORDER_BY = KEY_CHARTING_DATE + " DESC";
    private static final String[] MAX_CREATED_AT_COLUMNS = { "max(" + StatusData.KEY_CHARTING_DATE + ")" };
    private static final String[] DB_TEXT_COLUMNS = { KEY_CHARTING_NOTES };

    //called once
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL( "CREATE table " + DATABASE_TABLE + " (" +
                                    KEY_ROWID + " INTEGER  primary key AUTOINCREMENT, " +
                                    KEY_CHARTING_DATE + " TEXT NOT NULL, " +
                                    KEY_NAME + " TEXT, " +
                                    KEY_CHARTING_TEMPERATURE + " INTEGER, " +
                                    KEY_CHARTING_STAMPS  + " INTEGER, " +
                                    KEY_CHARTING_FERTILE + " TEXT, " +
                                    KEY_CHARTING_NOTES + " TEXT, " +
                                    KEY_CHARTING_PROC +  " ); "
                );
    }

    final DbHelper dbHelper;

    public StatusData(Context context) {
          this.dbHelper = new DbHelper(context);
    }

    public void close() {
      this.dbHelper.close();
    }

    public void insertOrIgnore(ContentValues values) {
      SQLiteDatabase db = this.dbHelper.getWritableDatabase();
      try {
        db.insertWithOnConflict(DATABASE_TABLE, null, values,
            SQLiteDatabase.CONFLICT_IGNORE);
      } finally {
        db.close();
      }
    }

    /**
     *
     * @return Cursor where the columns are going to be id, created_at, user, txt
     */
    public Cursor getStatusUpdates() {
      SQLiteDatabase db = this.dbHelper.getReadableDatabase();
      return db.query(DATABASE_TABLE, null, null, null, null, null, GET_ALL_ORDER_BY);
    }

    public long getLatestStatusCreatedAtTime() {
      SQLiteDatabase db = this.dbHelper.getReadableDatabase();
      try {
        Cursor cursor = db.query(DATABASE_TABLE, MAX_CREATED_AT_COLUMNS, null, null, null,
            null, null);
        try {
          return cursor.moveToNext() ? cursor.getLong(0) : Long.MIN_VALUE;
        } finally {
          cursor.close();
        }
      } finally {
        db.close();
      }
    }

    public String getStatusTextById(long id) {
      SQLiteDatabase db = this.dbHelper.getReadableDatabase();
      try {
        Cursor cursor = db.query(DATABASE_TABLE, DB_TEXT_COLUMNS, KEY_ROWID + "=" + id, null,
            null, null, null);
        try {
          return cursor.moveToNext() ? cursor.getString(0) : null;
        } finally {
          cursor.close();
        }
      } finally {
        db.close();
      }
    }

    /**
     * Deletes ALL the data
     */
    public void delete() {
      // Open Database
      SQLiteDatabase db = dbHelper.getWritableDatabase();

      // Delete the data
      db.delete(DATABASE_TABLE, null, null);

      // Close Database
      db.close();
    }
}

添加到清单:

<application>
 ...
<provider android:name=".StatusProvider" android:authorities="com.projectcaruso.naturalfamilyplaning"/>
</application>

编辑:

    05-16 21:41:20.514: E/ActivityThread(7147): Failed to find provider info for com.projectcaruso.naturalfamilyplaning.statusprovider
    05-16 21:41:20.514: V/SlidingMenu(7147): changing layerType. hardware? true
    05-16 21:41:20.584: D/dalvikvm(7147): GC_FOR_ALLOC freed 2595K, 8% free 3305K/3564K, paused 33ms, total 42ms
    05-16 21:41:20.594: I/dalvikvm-heap(7147): Grow heap (frag case) to 4.476MB for 1188736-byte allocation
    05-16 21:41:20.694: D/dalvikvm(7147): GC_CONCURRENT freed 1K, 6% free 4464K/4728K, paused 73ms+5ms, total 105ms
    05-16 21:41:20.694: D/dalvikvm(7147): WAIT_FOR_CONCURRENT_GC blocked 19ms
    05-16 21:41:20.744: D/dalvikvm(7147): GC_FOR_ALLOC freed <1K, 6% free 4464K/4728K, paused 30ms, total 30ms
    05-16 21:41:20.754: I/dalvikvm-heap(7147): Grow heap (frag case) to 5.870MB for 1463056-byte allocation
    05-16 21:41:20.864: D/dalvikvm(7147): GC_CONCURRENT freed 0K, 5% free 5893K/6160K, paused 76ms+5ms, total 107ms
    05-16 21:41:20.864: D/dalvikvm(7147): WAIT_FOR_CONCURRENT_GC blocked 18ms
    05-16 21:41:20.894: I/Choreographer(7147): Skipped 47 frames!  The application may be doing too much work on its main thread.
    05-16 21:41:20.937: V/CustomViewBehind(7147): behind INVISIBLE
    05-16 21:41:21.025: V/SlidingMenu(7147): changing layerType. hardware? false

编辑2:

    05-17 13:20:41.013: D/dalvikvm(21373): GC_CONCURRENT freed 0K, 12% free 6199K/7004K, paused 73ms+6ms, total 111ms
    05-17 13:20:41.013: D/dalvikvm(21373): WAIT_FOR_CONCURRENT_GC blocked 24ms
    05-17 13:20:41.054: V/SlidingMenu(21373): changing layerType. hardware? true
    05-17 13:20:41.054: V/SlidingMenu(21373): changing layerType. hardware? false
    05-17 13:20:41.073: I/Choreographer(21373): Skipped 54 frames!  The application may be doing too much work on its main thread.
    05-17 13:20:41.844: D/StatusProvider(21373): querying
    05-17 13:20:41.855: I/Choreographer(21373): Skipped 39 frames!  The application may be doing too much work on its main thread.
    05-17 13:20:41.924: V/SlidingMenu(21373): changing layerType. hardware? true
    05-17 13:20:41.984: W/CursorWrapperInner(21373): Cursor finalized without prior close()
    05-17 13:20:41.984: D/dalvikvm(21373): GC_FOR_ALLOC freed 2601K, 49% free 3627K/7004K, paused 35ms, total 43ms
    05-17 13:20:41.994: I/dalvikvm-heap(21373): Grow heap (frag case) to 4.791MB for 1188736-byte allocation
    05-17 13:20:42.104: D/dalvikvm(21373): GC_CONCURRENT freed 23K, 32% free 4765K/7004K, paused 73ms+5ms, total 113ms
    05-17 13:20:42.104: D/dalvikvm(21373): WAIT_FOR_CONCURRENT_GC blocked 35ms
    05-17 13:20:42.154: D/dalvikvm(21373): GC_FOR_ALLOC freed 1K, 32% free 4764K/7004K, paused 36ms, total 36ms
    05-17 13:20:42.154: I/dalvikvm-heap(21373): Grow heap (frag case) to 6.163MB for 1463056-byte allocation
    05-17 13:20:42.265: D/dalvikvm(21373): GC_CONCURRENT freed 0K, 12% free 6193K/7004K, paused 74ms+5ms, total 110ms
    05-17 13:20:42.265: D/dalvikvm(21373): WAIT_FOR_CONCURRENT_GC blocked 29ms
    05-17 13:20:42.294: V/SlidingMenu(21373): changing layerType. hardware? true
    05-17 13:20:42.294: I/Choreographer(21373): Skipped 45 frames!  The application may be doing too much work on its main thread.
    05-17 13:20:42.335: V/CustomViewBehind(21373): behind INVISIBLE
    05-17 13:20:42.424: V/SlidingMenu(21373): changing layerType. hardware? false

1 个答案:

答案 0 :(得分:1)

中有错误
public static final Uri CONTENT_URI = Uri
        .parse("content://com.projectcaruso.naturalfamilyplaning.statusprovider");

应该是

public static final Uri CONTENT_URI = Uri
        .parse("content://com.projectcaruso.naturalfamilyplaning/statusprovider");

uri解析器通过“/”解析元素而不是点解析。因此,无法找到提供者,因为您的清单中没有声明“com.projectcaruso.naturalfamilyplaning.statusprovider”权限。