2012-01-18 36 views
5

Tôi đang cập nhật ứng dụng Android 2.2 để sử dụng CursorLoader (sử dụng thư viện tương thích v4) và tôi đang cố gắng giải thích tại sao phương thức onLoadFinished không được gọi khi nhà cung cấp nội dung thông báo thay đổi về nội dung liên quan đến truy vấn CursorLoader.Android CursorLoader không phản hồi các thông báo ContentProvider

CursorLoader đang truy vấn nhà cung cấp nội dung khách hàng. nhà cung cấp của tôi đặt ra thông báo URI trong phương pháp truy vấn của nó:

cursor.setNotificationUri(getContext().getContentResolver(), uri); 

và thông báo những thay đổi trong chèn nó/cập nhật/xóa các phương pháp:

getContext().getContentResolver().notifyChange(uri, null); 

Tôi đã kiểm tra rằng URI là giống hệt nhau trong cả hai trường hợp. Trước đây tôi đã sử dụng ManagedQuery với cùng một nhà cung cấp nội dung và nội dung được truy vấn đã được cập nhật tốt, điều này khiến tôi nghĩ rằng nhà cung cấp nội dung có thể là ok.

Tôi đã xem ví dụ LoaderCursorSupport và thú vị khi chạy trên Nexus One Tôi không thấy nó phản ánh những thay đổi tôi thực hiện cho tên liên hệ (chuyển đổi giữa ứng dụng mẫu và ứng dụng danh bạ). Phải không? Nếu vậy, có một số vấn đề cơ bản mà tôi không biết?

+0

bạn có thể cung cấp một số mã để giúp chúng tôi xác định vấn đề không? –

+0

Bật gỡ lỗi có thể hữu ích, 'LoaderManager.enableDebugLogging (true)' –

+0

Cảm ơn mẹo gỡ lỗi. Mã máy khách của tôi về bản chất giống như ví dụ LoaderCursorSupport mà tôi đã tham chiếu. Cho rằng điều này thể hiện cùng một vấn đề, tôi đã hiểu lầm cách CursorLoader được cho là hoạt động tức là nếu tôi chạy ví dụ hỗ trợ để hiển thị danh sách liên hệ, sau đó chỉnh sửa số liên lạc trong sổ địa chỉ, nó sẽ không thay đổi trong danh sách được hiển thị bởi ứng dụng ví dụ? – siwatson

Trả lời

-1

Có lẽ bạn nên sử dụng bối cảnh ứng dụng:

getContext().getApplicationContext().getContentResolver().notifyChange(uri, null); 
+0

Điều này không tạo ra bất kỳ sự khác biệt nào tôi sợ. – siwatson

4

cuối cùng tôi đã đến đáy này và, như thường là đường đi, nó là một sai lầm ngu ngốc trên một phần của tôi. Tôi đã gọi hàm cursor.close() trong phương thức onLoadFinished() của tôi - tôi sử dụng con trỏ trả về để tạo một ArrayAdapter (tôi cần chèn một mục ở đầu danh sách) và đóng con trỏ là một phần còn lại từ việc sử dụng một ManagedQuery trước khi di chuyển để sử dụng CursorLoader.

Trong quá trình tìm kiếm điều này, tôi đã tạo một lớp thử nghiệm đơn giản để hiển thị danh sách dấu trang và thêm dấu trang ngẫu nhiên (sử dụng trình đơn tùy chọn). Điều này có tác dụng vì nó được gọi là onLoadFinished() được gọi sau khi mục được thêm vào. Đây là mã trong trường hợp mã này hữu ích cho bất kỳ ai khác:

package com.test; 

import android.content.ContentValues; 
import android.database.Cursor; 
import android.os.Bundle; 
import android.provider.Browser; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.ListFragment; 
import android.support.v4.app.LoaderManager; 
import android.support.v4.content.CursorLoader; 
import android.support.v4.content.Loader; 
import android.support.v4.view.MenuItemCompat; 
import android.support.v4.widget.SimpleCursorAdapter; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MenuInflater; 
import android.view.MenuItem; 

public class CursorLoaderTestActivity extends FragmentActivity 
{ 
    private static final String TAG = CursorLoaderTestActivity.class.getSimpleName(); 

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

     FragmentManager fm = getSupportFragmentManager(); 

     // Create the list fragment and add it as our sole content. 
     if (fm.findFragmentById(android.R.id.content) == null) 
     { 
      CursorLoaderListFragment list = new CursorLoaderListFragment(); 
      fm.beginTransaction().add(android.R.id.content, list).commit(); 
     } 
    } 


    public static class CursorLoaderListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> 
    { 

     // This is the Adapter being used to display the list's data. 
     SimpleCursorAdapter mAdapter; 

     // If non-null, this is the current filter the user has provided. 
     String mCurFilter; 

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

      // Give some text to display if there is no data. In a real 
      // application this would come from a resource. 
      setEmptyText("No data"); 

      // We have a menu item to show in action bar. 
      setHasOptionsMenu(true); 

      // Create an empty adapter we will use to display the loaded data. 
      mAdapter = new SimpleCursorAdapter(getActivity(), 
        android.R.layout.simple_list_item_1, null, 
        new String[] { Browser.BookmarkColumns.TITLE }, 
        new int[] { android.R.id.text1}, 0); 

      setListAdapter(mAdapter); 

      // Start out with a progress indicator. 
      setListShown(false); 

      // Prepare the loader. Either re-connect with an existing one, 
      // or start a new one. 
      getLoaderManager().initLoader(0, null, this); 
     } 

     //@Override 
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) 
     { 
      // Place an action bar item for searching. 
      MenuItem item = menu.add("Add Item"); 
      //item.setIcon(android.R.drawable.ic_menu_search); 
      MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS); 
     } 

     @Override 
     public boolean onOptionsItemSelected (MenuItem item) 
     { 
      ContentValues cv=new ContentValues(); 
      cv.put(Browser.BookmarkColumns.TITLE, "!AA " + System.currentTimeMillis()); 
      cv.put(Browser.BookmarkColumns.URL, "http://test/"); 
      cv.put(Browser.BookmarkColumns.BOOKMARK, 1); 
      getActivity().getContentResolver().insert(Browser.BOOKMARKS_URI, cv); 
      return true; 
     } 

     //columns to query 
     static final String[] PROJECTION = new String[] { Browser.BookmarkColumns.TITLE }; 


     public Loader<Cursor> onCreateLoader(int id, Bundle args) 
     { 
      Log.i(TAG, "onCreateLoader"); 

      return new CursorLoader(getActivity(), Browser.BOOKMARKS_URI, 
        PROJECTION, null, null, 
        Browser.BookmarkColumns.TITLE + " ASC"); 
     } 

     public void onLoadFinished(Loader<Cursor> loader, Cursor data) 
     { 
      Log.i(TAG, "onLoadFinished"); 

      // Swap the new cursor in. (The framework will take care of closing the 
      // old cursor once we return.) 
      mAdapter.swapCursor(data); 

      // The list should now be shown. 
      if (isResumed()) 
       setListShown(true); 
      else 
       setListShownNoAnimation(true); 
     } 

     public void onLoaderReset(Loader<Cursor> loader) 
     { 
      // This is called when the last Cursor provided to onLoadFinished() 
      // above is about to be closed. We need to make sure we are no 
      // longer using it. 
      mAdapter.swapCursor(null); 
     } 
    } 

} 
+0

Có. Con trỏ nên được giữ cho đến khi cái khác được cung cấp trong onLoadFinished(). – f470071

Các vấn đề liên quan