在安卓中四大组件之一ContentProvider进程就不一致,于是我就改自己这边逻辑,也取和改数据通过我的大家一定不陌生,我最近在优化自己的模块时发生一个BUG,我是提供Provider数据的app,但是其他来取我数据的app和我保存的值不一样。

后来发现因为我是用SharedPreferences+ContentProvider的方式存储数据提供给各个APP的,原来我的主程序代码和Provider在一个进程下,但调我Provider的APP太多了,导致我的程序即使退出在后台也占用内存不会杀死,于是把Provider独立了另一个进程,于是主进程就能释放内存了。但是引起了以上问题。

经过查了很多文章,推敲应该是由于SharedPreferences在多线程下的确会取得数据不一致,看到一个大佬的回答有所启发。我以前取数据都是直接从自己目录下SharedPreferences里拿的,那进程就是我主程序的进程,和提供其他APP数据的Provider进程就不一致,于是我就改自己这边逻辑,也取和改数据通过我的Provider来操作,终于解决了这个问题。

public static UserInfoBean getLoginedUserInfo () { UserInfoBean userInfo = null; ContentResolver cr = UcApp.sCtx.getContentResolver(); Cursor cursor = cr.query(Const.URI.USER_INFO, null, null, null, null); if ( null == cursor ) { LogUtils.w("getLoginedUserInfo cursor == null"); return userInfo; } Bundle bundle = cursor.getExtras(); boolean isLogined = bundle.getBoolean(Const.SpUser.Key.IS_LOGINED, false); if ( ! isLogined ) { LogUtils.w("getLoginedUserInfo isLogined = false"); return userInfo; } userInfo = new UserInfoBean(); userInfo.isLogined = true; userInfo.username = bundle.getString(Const.SpUser.Key.USERNAME, ""); userInfo.token = bundle.getString(Const.SpUser.Key.TOKEN, ""); cursor.close(); LogUtils.w(userInfo.toString()); return userInfo;} public static void saveLoginedUserInfo (UserInfoBean userInfo, boolean isSaveToken) { if ( null == userInfo ) { return; } ContentResolver cr = UcApp.sCtx.getContentResolver(); ContentValues values = new ContentValues(); values.put(Const.SpUser.Key.IS_LOGINED, true); values.put(Const.SpUser.Key.USERNAME, userInfo.username); values.put(Const.SpUser.Key.TOKEN, userInfo.token); userInfo.usernameEncode = ComUtils.URLEncoder(userInfo.username); values.put(Const.SpUser.Key.USERNAME_ENCODE, userInfo.usernameEncode); cr.update(Const.URI.USER_INFO, values, null, null);} @Overridepublic Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor = new MatrixCursor(new String[]{}); Bundle bundle = new Bundle(); UserInfoBean userInfo = getLoginedUserInfo(); if ( null != userInfo ) { bundle.putBoolean(Const.SpUser.Key.IS_LOGINED, true); bundle.putString(Const.SpUser.Key.USERNAME, userInfo.username); bundle.putString(Const.SpUser.Key.TOKEN, userInfo.token); } else { bundle.putBoolean(Const.SpUser.Key.IS_LOGINED, false); } } LogUtils.w(bundle.toString()); return cursor;}@Overridepublic int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) { if ( null == values ) { return 0; } LogUtils.w(values.toString()); SpUtils spUtils = new SpUtils(Const.SpUser.NAME); Set<String> keys = values.keySet(); for ( String key : keys ) { Object obj = values.get(key); if ( null != obj ) { spUtils.add(key, obj); } } spUtils.apply(); notifyChangeUserInfo(); return 1;}private UserInfoBean getLoginedUserInfo () { UserInfoBean userInfo = null; SpUtils spUtils = new SpUtils(Const.SpUser.NAME); boolean isLogined = (boolean) spUtils.get(Const.SpUser.Key.IS_LOGINED, false); if ( ! isLogined ) { LogUtils.w("isLogined = false"); return userInfo; } userInfo = new UserInfoBean(); userInfo.isLogined = true; userInfo.username = (String) spUtils.get(Const.SpUser.Key.USERNAME, ""); userInfo.token = (String) spUtils.get(Const.SpUser.Key.TOKEN, ""); return userInfo;}