在我的应用程序中,我使用了一个内容提供商。如您所知,内容提供者是客户机和SQLite之间的中间人。在我的例子中,我使用volley从服务器上检索数据,将它们存储在SQLite中,最后使用ContentResolver对象和LoaderManager接口(其中包含onCreateLoader、onLoadFinished、onLoaderReset)读取它们。当应用程序关闭时,我也使用服务,因为我想运行我的webservice。
MyService
  public class MyService extends IntentService {
  private final String LOG_TAG = MyService.class.getSimpleName();
  public MyService() {
    super("My Service");
  }
  @Override
  protected void onHandleIntent(Intent intent) {
    updateCityList();
  }
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }
  public void updateCityList() {
    cityList.clear();
    // Instantiate the RequestQueue.
    RequestQueue queue = Volley.newRequestQueue(this);
    // Request a string response from the provided URL.
    JsonArrayRequest jsObjRequest = new JsonArrayRequest(Request.Method.GET, 
   API.API_URL, new Response.Listener<JSONArray>() {
        @Override
        public void onResponse(JSONArray response) {
            Log.d(TAG, response.toString());
            //hidePD();
            // Parse json data.
            // Declare the json objects that we need and then for loop through the children array.
            // Do the json parse in a try catch block to catch the exceptions
            try {
                for (int i = 0; i < response.length(); i++) {
                    JSONObject post = response.getJSONObject(i);
                    MyCity item = new MyCity();
                    item.setName(post.getString("title"));
                    item.setImage(API.IMAGE_URL + post.getString("image"));
                    ContentValues imageValues = new ContentValues();
                    imageValues.put(MyCityContract.MyCityEntry._ID, post.getString("id"));
                    imageValues.put(MyCityContract.MyCityEntry.COLUMN_NAME, post.getString("title"));
                    imageValues.put(MyCityContract.MyCityEntry.COLUMN_ICON, post.getString("image"));
                    getContentResolver().insert(MyCityContract.MyCityEntry.CONTENT_URI, imageValues);
                    cityList.add(item);
                    cityList.add(item);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
            // Update list by notifying the adapter of changes
            myCityAdpapter.notifyDataSetChanged();
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            VolleyLog.d(TAG, "Error: " + error.getMessage());
            //hidePD();
        }
    });
    queue.add(jsObjRequest);
}
static public class AlarmReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent sendIntent = new Intent(context, MyService.class);
        context.startService(sendIntent);
    }
   }
}MainActivityFragment
 public class MainActivityFragment extends Fragment implements    
 LoaderManager.LoaderCallbacks<Cursor>{
 static public ArrayList<MyCity> cityList;
 public String [] MY_CITY_PROJECTIONS = {MyCityContract.MyCityEntry._ID,
        MyCityContract.MyCityEntry.COLUMN_NAME,
        MyCityContract.MyCityEntry.COLUMN_ICON};
private static final String LOG_TAG =    
MainActivityFragment.class.getSimpleName();
public static MyCityAdpapter myCityAdpapter;
private static final int CURSOR_LOADER_ID = 0;
private GridView mGridView;
public MainActivityFragment() {
    // Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Add this line in order for this fragment to handle menu events.
    setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.refresh, menu);
}
@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();
    if (id == R.id.action_refresh) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    // inflate fragment_main layout
    final View rootView = inflater.inflate(R.layout.fragment_main_activity, container, false);
    cityList = new ArrayList<>();
    // initialize our FlavorAdapter
    myCityAdpapter = new MyCityAdpapter(getActivity(), null, 0, CURSOR_LOADER_ID);
    // initialize mGridView to the GridView in fragment_main.xml
    mGridView = (GridView) rootView.findViewById(R.id.flavors_grid);
    // set mGridView adapter to our CursorAdapter
    mGridView.setAdapter(myCityAdpapter);
    Cursor c =
            getActivity().getContentResolver().query(MyCityContract.MyCityEntry.CONTENT_URI,
                    new String[]{MyCityContract.MyCityEntry._ID},
                    null,
                    null,
                    null);
    if (c.getCount() == 0){
        updateCityData();
    }
    // initialize loader
    getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this);
    super.onCreate(savedInstanceState);
    return rootView;
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args){
    return new CursorLoader(getActivity(),
            MyCityContract.MyCityEntry.CONTENT_URI,
            MY_CITY_PROJECTIONS,
            null,
            null,
            null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    myCityAdpapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader){
    myCityAdpapter.swapCursor(null);
}
public void updateCityData() {
    Intent alarmIntent = new Intent(getActivity(), MyService.AlarmReceiver.class);
    //Wrap in a pending intent which only fires once.
    PendingIntent pi = PendingIntent.getBroadcast(getActivity(), 0,alarmIntent,PendingIntent.FLAG_ONE_SHOT);//getBroadcast(context, 0, i, 0);
    AlarmManager am=(AlarmManager)getActivity().getSystemService(Context.ALARM_SERVICE);
    //Set the AlarmManager to wake up the system.
    am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, pi);
    }
 }我只是设置了一个警报管理器,使我的服务运行5秒后。这只是为了真正的测试。不管怎样,这是我的问题。当我第一次启动应用程序时,屏幕上没有显示任何内容。但是,当我退出并再次启动它时,我可以在我的网格视图中看到所有的图像。为什么会发生这种情况?更清楚地
当我第一次启动这个应用程序时:
10-16 12:07:00.799 16685-16685/theo.testing.androidcustomloaders D/ContentValues: [{"id":"15","title":"The Gate of Larissa","image":"larissa17.png"},{"id":"14","title":"Larissa Fair","image":"larissa14.png"},{"id":"13","title":"Larissa Fair","image":"larissa13.png"},{"id":"12","title":"AEL FC Arena","image":"larissa12.png"},{"id":"11","title":"AEL FC Arena","image":"larissa11.png"},{"id":"10","title":"Alcazar Park","image":"larissa10.png"},{"id":"9","title":"Alcazar Park","image":"larissa9.png"},{"id":"8","title":"Church","image":"larissa8.png"},{"id":"7","title":"Church","image":"larissa7.png"},{"id":"6","title":"Old trains","image":"larissa6.png"},{"id":"5","title":"Old trains","image":"larissa5.png"},{"id":"4","title":"Munipality Park","image":"larissa4.png"},{"id":"3","title":"Munipality Park","image":"larissa3.png"},{"id":"2","title":"Ancient Theatre - Larissa","image":"larissa2.png"},{"id":"1","title":"Ancient Theatre - Larissa","image":"larissa1.png"}]为了显示数据,我需要退出应用程序并再次启动它。为什么会发生这种情况?我的密码有什么问题吗?
发布于 2016-10-17 07:19:11
LoadManager不处理数据库中的更改,因为它与数据库没有任何连接。你必须注册观察员来处理这些事情。
在您的myCityProvider中,query(...)方法中缺少setNotificationUri方法。它应该设置在最后。
下面是修改您的query方法:
@Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Cursor retCursor;
        switch (sUriMatcher.match(uri)) {
            // All Flavors selected
            case MY_CITY: {
                retCursor = myCityDbHelper.getReadableDatabase().query(
                        MyCityContract.MyCityEntry.TABLE_MY_CITY,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder);
                break;
            }
            // Individual flavor based on Id selected
            case MY_CITY_WITH_ID: {
                retCursor = myCityDbHelper.getReadableDatabase().query(
                        MyCityContract.MyCityEntry.TABLE_MY_CITY,
                        projection,
                        MyCityContract.MyCityEntry._ID + " = ?",
                        new String[]{String.valueOf(ContentUris.parseId(uri))},
                        null,
                        null,
                        sortOrder);
                break;
            }
            default: {
                // By default, we assume a bad URI
                throw new UnsupportedOperationException("Unknown uri: " + uri);
            }
        }
        if (retCursor != null) {
            retCursor.setNotificationUri(getContext().getContentResolver(), uri);
        }
        return retCursor;
    }我检查过你的git,我认为你应该修复你的MainActivityFragment。您在onCreateView中做所有的事情,但是您应该在这里做所有与视图相关的事情,或者只返回膨胀的视图。在此之后,您可以在onViewCreated中完成其余的工作。
你应该这样做:
@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_main_activity, container, false);
    }
    @Override
    public void onViewCreated(View rootView, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(rootView, savedInstanceState);
        myCityAdpapter = new MyCityAdpapter(getActivity(), null, 0);
        mGridView = (GridView) rootView.findViewById(R.id.flavors_grid);
        mGridView.setAdapter(myCityAdpapter);
        getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this);
    }
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        switch (id) {
            case CURSOR_LOADER_ID:
                return new CursorLoader(getActivity(),
                        MyCityContract.MyCityEntry.CONTENT_URI,
                        null,
                        null,
                        null,
                        null);
            default:
                throw new IllegalArgumentException("id not handled!");
        }
    }
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        switch (loader.getId()) {
            case CURSOR_LOADER_ID:
                if (data == null || data.getCount() == 0) {
                    updateCityData();
                } else {
                    myCityAdpapter.swapCursor(data);
                }
                break;
        }
    }
    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        myCityAdpapter.swapCursor(null);
    }由于这一点:
https://stackoverflow.com/questions/40068699
复制相似问题