【问题标题】:How to refresh a ListFragment using a content provider from another Activity?如何使用来自另一个 Activity 的内容提供程序刷新 ListFragment?
【发布时间】:2014-01-06 17:33:39
【问题描述】:

我有一个 Fragment List 类(如下),用于使用 Content Provider 显示本地 SQLite 数据库中的值。

public static ContentResolver resolver;
Uri uri;
AsyncQueryHandler handler;
public static SimpleCursorAdapter adapter;
private Cursor localCursor;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    resolver = this.getActivity().getContentResolver();
    uri = Uri
            .parse("content://com.n00111715.messengerlist.model.MessageContentProvider/messages");
    handler = new AsyncQueryHandler(resolver) {
        public void onQueryComplete(int token, Object cookie, Cursor cursor) {
            MessageListFragment.this.onQueryComplete(cursor);
        }
    };
    handler.startQuery(0, null, uri, null, null, null, null);
}

public void onQueryComplete(Cursor cursor) {
    // store the cursor values
    localCursor = cursor;

    String[] from = new String[] { "_id", "reciever", "sender", "subject",
            "date", "message" };

    int[] to = new int[] { R.id.hidden_id_field, R.id.hidden_to_field,
            R.id.list_item_message_from_textview,
            R.id.list_item_message_subject_textview,
            R.id.list_item_message_date_textview,
            R.id.list_item_message_content_textview };

    // create a simple cursor adapter that used the cursor from the
    // database, and maps the values
    // to the textviews in the list items that make up the list fragment        
    adapter = new SimpleCursorAdapter(this.getActivity(),
            R.layout.list_item_message, cursor, from, to, 0);
    // set this as this list fragments adapter
    setListAdapter(adapter);
}

public void onListItemClick(ListView l, View v, int position, long id) {

    String currentId = String.valueOf(id);
    int i = 0;
    String[] values = new String[6];

    // loop through the cursor object
    localCursor.moveToFirst();
    while (localCursor.isAfterLast() == false) {
        // extract this row values for the id column, if the match the
        // selected id
        if (localCursor.getString(0).equals(currentId)) {
            // loop through the values of the full row
            for (int j = 0; j < values.length; j++) {
                // add these values to the values string array
                values[j] = localCursor.getString(j);
            }
        }
        i++;
        localCursor.moveToNext();
    }
    // create new intent
    Intent intent = new Intent(getActivity(), ViewingMessageActivity.class);
    // add the selected messages values into extras
    intent.putExtra("values", values);
    // start the ne activity
    startActivity(intent);
}

当我在列表中选择一个项目时,会显示一个Activity(如下)。

    // variable for the UI elements
Button deleteButton, saveButton, forwardButton;
EditText editTextFrom, editTextSubject, editTextContent;
//MessageListFragment mlf;
String[] values;
Intent intent;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // set the layout file for this activity
    setContentView(R.layout.viewing_fragment_layout);

    // get the the intent
    intent = getIntent();

    // retrieve the string array from extras
    values = intent.getStringArrayExtra("values");
    Log.d("this is my array", "values: " + Arrays.toString(values));
    getReferences();
    populateUIFields();
}

private void populateUIFields() {
    // insert message values into the text fields
    editTextFrom.setText(values[2]); // from
    editTextSubject.setText(values[3]); // subject
    editTextContent.setText(values[4]); // content
}

private void getReferences() {
    // get references to the ui elements
    deleteButton = (Button) findViewById(R.id.deleteButton);
    saveButton = (Button) findViewById(R.id.saveButton);
    forwardButton = (Button) findViewById(R.id.forwardButton);
    editTextFrom = (EditText) findViewById(R.id.editTextFrom);
    editTextSubject = (EditText) findViewById(R.id.editTextSubject);
    editTextContent = (EditText) findViewById(R.id.editTextContent);
    // add click listeners to each button
    deleteButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            String whereClause = "_id = " + values[0];
            ContentResolver resolver = getApplicationContext()
                    .getContentResolver();
            Uri uri = Uri
                    .parse("content://com.n00111715.messengerlist.model.MessageContentProvider/messages");
            AsyncQueryHandler handler = new AsyncQueryHandler(resolver) {
                public void onDeleteComplete(int token, Object cookie,
                        int result) {
                    ViewingMessageActivity.this.onDeleteComplete(result);
                }
            };
            handler.startDelete(0, null, uri, whereClause, null);
        }
    });

    saveButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {

            values[2] = editTextFrom.getText().toString();
            values[3] = editTextSubject.getText().toString();
            values[4] = editTextContent.getText().toString();

            ContentValues row = new ContentValues();
            row.put("reciever", values[1]);
            row.put("sender", values[2]);
            row.put("subject", values[3]);
            row.put("message", values[4]);
            row.put("date", values[5]);

            String whereClause = "_id = " + values[0];

            ContentResolver resolver = getApplicationContext()
                    .getContentResolver();
            Uri uri = Uri
                    .parse("content://com.n00111715.messengerlist.model.MessageContentProvider/messages");
            AsyncQueryHandler handler = new AsyncQueryHandler(resolver) {
                public void onUpdateComplete(int token, Object cookie,
                        int result) {
                    ViewingMessageActivity.this.onSaveComplete(result);
                }
            };
            handler.startUpdate(0, null, uri, row, whereClause, null);
        }
    });

}

protected void onDeleteComplete(int result) {
    Toast.makeText(getApplicationContext(), "message deleted",
            Toast.LENGTH_LONG).show();
    //return to the list fragment and refresh the list

}

protected void onSaveComplete(int result) {
    Toast.makeText(getApplicationContext(), "message saved",
            Toast.LENGTH_LONG).show();
    //return to the list fragment and refresh the list
} 

当从此类内部更新数据库时,我想返回列表片段(处置当前活动?)并刷新列表以显示数据的任何更改。

我想我需要为这个列表片段创建一个新的数据库查询和一个新的适配器。我不确定我应该如何从查看活动中解决这个问题。

我找到了this answer that is similar to my problem,但我无法让它工作。

这就是Content Provider 的样子。

    public static final String AUTHORITY = "com.n00111715.messengerlist.model.MessageContentProvider";
private static final UriMatcher sUriMatcher;
private static final int MESSAGE_COLLECTION_URI_INDICATOR = 1;
private static final int SINGLE_MESSAGE_URI_INDICATOR = 2;

public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
        + "/" + MessageTableGateway.TABLE_MESSAGES);
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.n00111715.messengerlist.model.message";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.n00111715.messengerlist.model.message";

static {
    sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    sUriMatcher.addURI(AUTHORITY, MessageTableGateway.TABLE_MESSAGES,
            MESSAGE_COLLECTION_URI_INDICATOR);
    sUriMatcher.addURI(AUTHORITY,
            MessageTableGateway.TABLE_MESSAGES + "/#",
            SINGLE_MESSAGE_URI_INDICATOR);
}

private MessageTableGateway mMessageTableGateway;
private ContentResolver mContentResolver;

@Override
public boolean onCreate() {
    Context context = getContext();
    mContentResolver = context.getContentResolver();

    MessengerListOpenHelper helper = MessengerListOpenHelper
            .getInstance(context);
    SQLiteDatabase db = helper.getWritableDatabase();
    mMessageTableGateway = MessageTableGateway.getInstance(db);
    return true;
}

@Override
public int update(Uri uri, ContentValues values, String whereClause,
        String[] whereArgs) {
    int count;

    switch (sUriMatcher.match(uri)) {
    case MESSAGE_COLLECTION_URI_INDICATOR:
        count = mMessageTableGateway.update(values, whereClause, whereArgs);
        break;
    case SINGLE_MESSAGE_URI_INDICATOR:
        String id = uri.getPathSegments().get(1);
        String where = MessageTableGateway.COLUMN_ID + " = " + id;

        if (TextUtils.isEmpty(whereClause)) {
            whereClause = where;
        } else {
            whereClause = where + " AND " + where;
        }
        count = mMessageTableGateway.update(values, whereClause, whereArgs);
        break;
    default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }
    mContentResolver.notifyChange(uri, null, false);


    return count;
}

@Override
public int delete(Uri uri, String whereClause, String[] whereArgs) {
    int count;

    switch (sUriMatcher.match(uri)) {
    case MESSAGE_COLLECTION_URI_INDICATOR:
        count = mMessageTableGateway.delete(whereClause, whereArgs);
        break;
    case SINGLE_MESSAGE_URI_INDICATOR:
        String id = uri.getPathSegments().get(1);
        String where = MessageTableGateway.COLUMN_ID + " = " + id;

        if (TextUtils.isEmpty(whereClause)) {
            whereClause = where;
        } else {
            whereClause = where + " AND " + where;
        }
        count = mMessageTableGateway.delete(whereClause, whereArgs);
        break;
    default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }
    mContentResolver.notifyChange(uri, null);

    return count;
}

@Override
public String getType(Uri uri) {
    switch (sUriMatcher.match(uri)) {
    case MESSAGE_COLLECTION_URI_INDICATOR:
        return CONTENT_TYPE;
    case SINGLE_MESSAGE_URI_INDICATOR:
        return CONTENT_ITEM_TYPE;
    default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }
}

@Override
public Uri insert(Uri uri, ContentValues values) {
    Uri insertedMessageUri;
    if (sUriMatcher.match(uri) != MESSAGE_COLLECTION_URI_INDICATOR) {
        throw new IllegalArgumentException("Unknown URI " + uri);
    }

    long id = mMessageTableGateway.insert(values);
    if (id > 0) {
        insertedMessageUri = ContentUris.withAppendedId(CONTENT_URI, id);
    } else {
        throw new SQLException("Failed to insert message into " + uri);
    }
    mContentResolver.notifyChange(insertedMessageUri, null);

    return insertedMessageUri;
}

@Override
public Cursor query(Uri uri, String[] columns, String whereClause,
        String[] whereArgs, String sortOrder) {
    Cursor c;

    switch(sUriMatcher.match(uri)) {
    case MESSAGE_COLLECTION_URI_INDICATOR:
        c = mMessageTableGateway.query(columns, whereClause, whereArgs, null, null, sortOrder, null);
        break;
    case SINGLE_MESSAGE_URI_INDICATOR:
        String id = uri.getPathSegments().get(1);
        String where = MessageTableGateway.COLUMN_ID + " = " + id;

        if (TextUtils.isEmpty(whereClause)) {
            whereClause = where;
        } else {
            whereClause = whereClause + " AND " + where;
        }
        c = mMessageTableGateway.query(columns, whereClause, whereArgs, null, null, sortOrder, null);
        break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
    }
    c.setNotificationUri(mContentResolver, uri);

    return c;
}

【问题讨论】:

    标签: java android android-listview android-fragments refresh


    【解决方案1】:

    添加一个 notifyChange 调用,该调用与您的列表片段正在查询的 uri 相同。它可能是没有添加特定行 ID 的更新 uri。

    【讨论】:

    • 感谢您的回复,如果我是完整的内容提供商,我仍然有点迷茫,您能否告诉我我需要做什么。我的列表片段正在查询以下 Uri:“content://com.n00111715.messengerlist.model.MessageContentProvider/messages”
    • 更新方法的 uri 是 content://..auth../messages/# 并且列表片段正在监视归因于消息 uri 的更改(没有行 id)。您只需要在 update() 方法中添加基本 uri 的通知: uri = Uri .parse("content://com.n00111715.messengerlist.model.MessageContentProvider/messages") mContentResolver.notifyChange(uri, null,假);
    【解决方案2】:

    如果您想自动执行此操作,您应该在您的活动中使用CursorLoader。使用这种方法的教程有很多。

    我向您推荐本教程:http://www.vogella.com/tutorials/AndroidSQLite/article.html(您的案例中最有趣的点是 9,但我建议您仔细阅读以了解全貌)

    我会指出最重要的几点:

    • 您的 Fragment 必须扩展 ListFragment
    • ListFragmentListView 必须有这个 ID @android:/id_list
    • 按照教程onCreateLoaderonLoadFinishedonLoaderReset中的描述实现这个接口LoaderManager.LoaderCallbacks&lt;Cursor&gt;及其3个方法
    • 使用您认为合适的SimpleCursorAdapter
    • 调用此方法非常重要getLoaderManager().initLoader(your_id, null, this);,因为your_id 是您的应用程序中定义的唯一Integer

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      • 2015-08-10
      • 2021-12-25
      • 2013-11-16
      • 1970-01-01
      • 2014-09-15
      • 1970-01-01
      相关资源
      最近更新 更多