getSharedPreferences(String name, int mode) of Service的实现(转)

本文详细解析了Android中Service类使用getSharedPreferences方法的过程。从Context抽象类开始,逐步跟踪到具体的实现细节,包括如何创建SharedPreferences实例以及如何传递ApplicationContext。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

I found a method getSharedPreferences(String name, int mode) in Service class

than I want to see how it implements

first I got a abstrat method in Context class

/android_opensource/frameworks/base/core/java/android/content/Context.java
...
262 /**
263 * Retrieve and hold the contents of the preferences file 'name', returning
264 * a SharedPreferences through which you can retrieve and modify its
265 * values. Only one instance of the SharedPreferences object is returned
266 * to any callers for the same name, meaning they will see each other's
267 * edits as soon as they are made.
268 *
269 * @param name Desired preferences file. If a preferences file by this name
270 * does not exist, it will be created when you retrieve an
271 * editor (SharedPreferences.edit()) and then commit changes (Editor.commit()).
272 * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
273 * default operation, {@link #MODE_WORLD_READABLE}
274 * and {@link #MODE_WORLD_WRITEABLE} to control permissions.
275 *
276 * @return Returns the single SharedPreferences instance that can be used
277 * to retrieve and modify the preference values.
278 *
279 * @see #MODE_PRIVATE
280 * @see #MODE_WORLD_READABLE
281 * @see #MODE_WORLD_WRITEABLE
282 */
283 public abstract SharedPreferences getSharedPreferences(String name,
284 int mode);
...


and Service extends ContextWrapper, ContextWrapper extends Context just implements from a new Context instance
/android_opensource/frameworks/base/core/java/android/content/ContextWrapper.java
...
132 @Override
133 public SharedPreferences getSharedPreferences(String name, int mode) {
134 return mBase.getSharedPreferences(name, mode);
135 }
...


so where does it pass the Context instance to the Service

The Context instance must implements the method

than I found the implementation in ApplicationContext which extends the Context

android_opensource/frameworks/base/core/java/android/app/ApplicationContext.java
...
@Override
303 public SharedPreferences getSharedPreferences(String name, int mode) {
304 SharedPreferencesImpl sp;
305 File f = makeFilename(getPreferencesDir(), name + ".xml");
306 synchronized (sSharedPrefs) {
307 sp = sSharedPrefs.get(f);
308 if (sp != null && !sp.hasFileChanged()) {
309 //Log.i(TAG, "Returning existing prefs " + name + ": " + sp);
310 return sp;
311 }
312 }
313
314 FileInputStream str = null;
315 File backup = makeBackupFile(f);
316 if (backup.exists()) {
317 f.delete();
318 backup.renameTo(f);
319 }
320
321 // Debugging
322 if (f.exists() && !f.canRead()) {
323 Log.w(TAG, "Attempt to read preferences file " + f + " without permission");
324 }
325
326 Map map = null;
327 if (f.exists() && f.canRead()) {
328 try {
329 str = new FileInputStream(f);
330 map = XmlUtils.readMapXml(str);
331 str.close();
332 } catch (org.xmlpull.v1.XmlPullParserException e) {
333 Log.w(TAG, "getSharedPreferences", e);
334 } catch (FileNotFoundException e) {
335 Log.w(TAG, "getSharedPreferences", e);
336 } catch (IOException e) {
337 Log.w(TAG, "getSharedPreferences", e);
338 }
339 }
340
341 synchronized (sSharedPrefs) {
342 if (sp != null) {
343 //Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map);
344 sp.replace(map);
345 } else {
346 sp = sSharedPrefs.get(f);
347 if (sp == null) {
348 sp = new SharedPreferencesImpl(f, mode, map);
349 sSharedPrefs.put(f, sp);
350 }
351 }
352 return sp;
353 }
354 }
...


but I still did't found where it pass the ApplicationContext in

after few minutes search I found another class ActivityThread

It had a method handleCreateService which should be called when create a Service

android_opensource/frameworks/base/core/java/android/app/ActivityThread.java
...
2436 private final void handleCreateService(CreateServiceData data) {
2437 // If we are getting ready to gc after going to the background, well
2438 // we are back active so skip it.
2439 unscheduleGcIdler();
2440
2441 PackageInfo packageInfo = getPackageInfoNoCheck(
2442 data.info.applicationInfo);
2443 Service service = null;
2444 try {
2445 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2446 service = (Service) cl.loadClass(data.info.name).newInstance();
2447 } catch (Exception e) {
2448 if (!mInstrumentation.onException(service, e)) {
2449 throw new RuntimeException(
2450 "Unable to instantiate service " + data.info.name
2451 + ": " + e.toString(), e);
2452 }
2453 }
2454
2455 try {
2456 if (localLOGV) Log.v(TAG, "Creating service " + data.info.name);
2457
2458 ApplicationContext context = new ApplicationContext();
2459 context.init(packageInfo, null, this);
2460
2461 Application app = packageInfo.makeApplication();
2462 context.setOuterContext(service);
2463 service.attach(context, this, data.info.name, data.token, app,
2464 ActivityManagerNative.getDefault());
2465 service.onCreate();
2466 mServices.put(data.token, service);
2467 try {
2468 ActivityManagerNative.getDefault().serviceDoneExecuting(data.token);
2469 } catch (RemoteException e) {
2470 // nothing to do.
2471 }
2472 } catch (Exception e) {
2473 if (!mInstrumentation.onException(service, e)) {
2474 throw new RuntimeException(
2475 "Unable to create service " + data.info.name
2476 + ": " + e.toString(), e);
2477 }
2478 }
2479 }
...


In the method it call the service's method attch and pass a ApplicationContext as parameter

then The service's attch method would pass the context throght the attachBaseContext(context) method
android_opensource/frameworks/base/core/java/android/app/Service.java
...
356 public final void attach(
357 Context context,
358 ActivityThread thread, String className, IBinder token,
359 Application application, Object activityManager) {
360 attachBaseContext(context);
361 mThread = thread; // NOTE: unused - remove?
362 mClassName = className;
363 mToken = token;
364 mApplication = application;
365 mActivityManager = (IActivityManager)activityManager;
366 }
...

android_opensource/frameworks/base/core/java/android/content/ContextWrapper.java
...
50 /**
51 * Set the base context for this ContextWrapper. All calls will then be
52 * delegated to the base context. Throws
53 * IllegalStateException if a base context has already been set.
54 *
55 * @param base The new base context for this wrapper.
56 */
57 protected void attachBaseContext(Context base) {
58 if (mBase != null) {
59 throw new IllegalStateException("Base context already set");
60 }
61 mBase = base;
62 }
...

so the service get the Context instance which implement the getSharedPreferences(String name, int mode) method

the original url [url]http://hi.baidu.com/ksoftware/blog/item/de17bbd6806b202507088bd8.html[/url]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值