SettingsProvider之Settings.System(Secure)内部类

来源:互联网 发布:js 强制刷新当前页面 编辑:程序博客网 时间:2024/05/14 22:11

转载请注明出处:http://blog.csdn.net/droyon/article/details/35558783

SettingsProvider采用了双缓冲,我们前面说过SettingsProvider中存在SettingsCache缓冲区,那么在Settings.java中还存在另外一个缓冲区,它就是NameValueCache。

1、
 NameValueTable用于描述SettingsProvider的数据表,封装了putString方法。  /**     * Common base for tables of name/value settings.     */    public static class NameValueTable implements BaseColumns {        public static final String NAME = "name";        public static final String VALUE = "value";        protected static boolean putString(ContentResolver resolver, Uri uri,                String name, String value) {            // The database will take care of replacing duplicates.            try {                ContentValues values = new ContentValues();                values.put(NAME, name);                values.put(VALUE, value);                resolver.insert(uri, values);                return true;            } catch (SQLException e) {                Log.w(TAG, "Can't set key " + name + " in " + uri, e);                return false;            }        }        public static Uri getUriFor(Uri uri, String name) {            return Uri.withAppendedPath(uri, name);        }    }


2、

2.1、封装了lazyGetProvider,根据uri得到相应的ContentProvider,此处为IContentProvider,binder跨进程数据访问。

2.2、封装了getStringForUser方法。此方法分两部分,首先得到long newValuesVersion = SystemProperties.getLong(mVersionSystemProperty, 0);,首先从本地cache中得到想要的数据,如果本地cache中不存在想要的数据,那么进行第二部分,查询数据库。

2.3,如果newVersion不等于目前的version,说明本地的cache和SettingsProvider中的数据存在不同步,需要清空本地cache,重新加载。

// Our own user's settings data uses a client-side cache                synchronized (this) {                    if (mValuesVersion != newValuesVersion) {                        if (LOCAL_LOGV || false) {                            Log.v(TAG, "invalidate [" + mUri.getLastPathSegment() + "]: current "                                    + newValuesVersion + " != cached " + mValuesVersion);                        }                        mValues.clear();                        mValuesVersion = newValuesVersion;                    }                    if (mValues.containsKey(name)) {                        return mValues.get(name);  // Could be null, that's OK -- negative caching                    }


顾名思义   nameValue   的缓冲池。// Thread-safe.    private static class NameValueCache {        private final String mVersionSystemProperty;        private final Uri mUri;        private static final String[] SELECT_VALUE =            new String[] { Settings.NameValueTable.VALUE };        private static final String NAME_EQ_PLACEHOLDER = "name=?";        // Must synchronize on 'this' to access mValues and mValuesVersion.        private final HashMap<String, String> mValues = new HashMap<String, String>();        private long mValuesVersion = 0;        // Initially null; set lazily and held forever.  Synchronized on 'this'.        private IContentProvider mContentProvider = null;        // The method we'll call (or null, to not use) on the provider        // for the fast path of retrieving settings.        private final String mCallGetCommand;        private final String mCallSetCommand;        public NameValueCache(String versionSystemProperty, Uri uri,                String getCommand, String setCommand) {//传入mCallGetCommand以及mCallSetCommand            mVersionSystemProperty = versionSystemProperty;            mUri = uri;            mCallGetCommand = getCommand;            mCallSetCommand = setCommand;        }        private IContentProvider lazyGetProvider(ContentResolver cr) {//IContentProvider的构造方法            IContentProvider cp = null;            synchronized (this) {                cp = mContentProvider;                if (cp == null) {                    cp = mContentProvider = cr.acquireProvider(mUri.getAuthority());                }            }            return cp;        }        public boolean putStringForUser(ContentResolver cr, String name, String value,                final int userHandle) {//putStringForUser            try {                Bundle arg = new Bundle();                arg.putString(Settings.NameValueTable.VALUE, value);                arg.putInt(CALL_METHOD_USER_KEY, userHandle);                IContentProvider cp = lazyGetProvider(cr);                cp.call(cr.getPackageName(), mCallSetCommand, name, arg);            } catch (RemoteException e) {                Log.w(TAG, "Can't set key " + name + " in " + mUri, e);                return false;            }            return true;        }        public String getStringForUser(ContentResolver cr, String name, final int userHandle) {            final boolean isSelf = (userHandle == UserHandle.myUserId());            if (isSelf) {                long newValuesVersion = SystemProperties.getLong(mVersionSystemProperty, 0);                // Our own user's settings data uses a client-side cache                synchronized (this) {                    if (mValuesVersion != newValuesVersion) {                        if (LOCAL_LOGV || false) {                            Log.v(TAG, "invalidate [" + mUri.getLastPathSegment() + "]: current "                                    + newValuesVersion + " != cached " + mValuesVersion);                        }                        mValues.clear();                        mValuesVersion = newValuesVersion;                    }                    if (mValues.containsKey(name)) {                        return mValues.get(name);  // Could be null, that's OK -- negative caching                    }                }            } else {                if (LOCAL_LOGV) Log.v(TAG, "get setting for user " + userHandle                        + " by user " + UserHandle.myUserId() + " so skipping cache");            }            IContentProvider cp = lazyGetProvider(cr);            // Try the fast path first, not using query().  If this            // fails (alternate Settings provider that doesn't support            // this interface?) then we fall back to the query/table            // interface.            if (mCallGetCommand != null) {                try {                    Bundle args = null;                    if (!isSelf) {                        args = new Bundle();                        args.putInt(CALL_METHOD_USER_KEY, userHandle);                    }                    Bundle b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);                    if (b != null) {                        String value = b.getPairValue();                        // Don't update our cache for reads of other users' data                        if (isSelf) {                            synchronized (this) {                                mValues.put(name, value);                            }                        } else {                            if (LOCAL_LOGV) Log.i(TAG, "call-query of user " + userHandle                                    + " by " + UserHandle.myUserId()                                    + " so not updating cache");                        }                        return value;                    }                    // If the response Bundle is null, we fall through                    // to the query interface below.                } catch (RemoteException e) {                    // Not supported by the remote side?  Fall through                    // to query().                }            }            Cursor c = null;            try {                c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE, NAME_EQ_PLACEHOLDER,                             new String[]{name}, null, null);                if (c == null) {                    Log.w(TAG, "Can't get key " + name + " from " + mUri);                    return null;                }                String value = c.moveToNext() ? c.getString(0) : null;                synchronized (this) {                    mValues.put(name, value);                }                if (LOCAL_LOGV) {                    Log.v(TAG, "cache miss [" + mUri.getLastPathSegment() + "]: " +                            name + " = " + (value == null ? "(null)" : value));                }                return value;            } catch (RemoteException e) {                Log.w(TAG, "Can't get key " + name + " from " + mUri, e);                return null;  // Return null, but don't cache it.            } finally {                if (c != null) c.close();            }        }    }

3、public static final class Bookmarks implements BaseColumns{
     public static Intent getIntentForShortcut(ContentResolver cr, char shortcut)//构建shortCut的intent
        {
            Intent intent = null;

            Cursor c = cr.query(CONTENT_URI,
                    sIntentProjection, sShortcutSelection,
                    new String[] { String.valueOf((int) shortcut) }, ORDERING);
            // Keep trying until we find a valid shortcut
            try {
                while (intent == null && c.moveToNext()) {
                    try {
                        String intentURI = c.getString(c.getColumnIndexOrThrow(INTENT));
                        intent = Intent.parseUri(intentURI, 0);
                    } catch (java.net.URISyntaxException e) {
                        // The stored URL is bad...  ignore it.
                    } catch (IllegalArgumentException e) {
                        // Column not found
                        Log.w(TAG, "Intent column not found", e);
                    }
                }
            } finally {
                if (c != null) c.close();
            }

            return intent;
        }



        public static Uri add(ContentResolver cr,
                                           Intent intent,
                                           String title,
                                           String folder,
                                           char shortcut,
                                           int ordering)
        {//加入书签
            // If a shortcut is supplied, and it is already defined for
            // another bookmark, then remove the old definition.
            if (shortcut != 0) {
                cr.delete(CONTENT_URI, sShortcutSelection,
                        new String[] { String.valueOf((int) shortcut) });
            }

            ContentValues values = new ContentValues();
            if (title != null) values.put(TITLE, title);
            if (folder != null) values.put(FOLDER, folder);
            values.put(INTENT, intent.toUri(0));
            if (shortcut != 0) values.put(SHORTCUT, (int) shortcut);
            values.put(ORDERING, ordering);
            return cr.insert(CONTENT_URI, values);
        }


public static CharSequence getTitle(Context context, Cursor cursor) {//得到title
            int titleColumn = cursor.getColumnIndex(TITLE);
            int intentColumn = cursor.getColumnIndex(INTENT);
            if (titleColumn == -1 || intentColumn == -1) {
                throw new IllegalArgumentException(
                        "The cursor must contain the TITLE and INTENT columns.");
            }

            String title = cursor.getString(titleColumn);
            if (!TextUtils.isEmpty(title)) {
                return title;
            }

            String intentUri = cursor.getString(intentColumn);
            if (TextUtils.isEmpty(intentUri)) {
                return "";
            }

            Intent intent;
            try {
                intent = Intent.parseUri(intentUri, 0);
            } catch (URISyntaxException e) {
                return "";
            }

            PackageManager packageManager = context.getPackageManager();
            ResolveInfo info = packageManager.resolveActivity(intent, 0);
            return info != null ? info.loadLabel(packageManager) : "";
        }
}

0 0
原创粉丝点击