1. 开篇 涉及的主要文件:
com.android.server.print
系统打印服务, 打印服务是一种插件( plug-in components),它能够通过一些标准协议和打印机通讯。这些服务像一座桥,处于系统和打印机之间。因此,打印机和打印协议的具体实现从系统中分离的,能够独立开发和更新。该处讲解的是和打印插件关联的系统服务.
/frameworks/base/services/print/java/com/android/server/print/
1 2 3 4 5 6 7 8 9 10 11 12 13 /home/newdisk/local/SPREADTRUM/liguang.zhang/remote_disk/sp8.1_trunk/frameworks/base/services/print/java/com/android/server/print$ lltotal 220 drwxr-xr-x 1 2516 2000 4096 Jun 25 14:20 ./ drwxr-xr-x 1 2516 2000 4096 Nov 8 2017 ../ -rw-r--r-- 1 2516 2000 41807 Jun 25 16:21 PrintManagerService.java -rw-r--r-- 1 2516 2000 34039 Jun 25 14:20 RemotePrintService.java -rw-r--r-- 1 2516 2000 8869 Jun 25 14:20 RemotePrintServiceRecommendationService.java -rw-r--r-- 1 2516 2000 34260 Nov 8 2017 RemotePrintSpooler.java -rw-r--r-- 1 2516 2000 85628 Jun 25 15:47 UserState.java
2. PrintManagerService初始化 PrintManagerService(简写PMS) 初始化
SystemServer中启动PMS
1 2 3 4 5 6 7 8 9 10 11 12 13 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PRINTING)) { traceBeginAndSlog("StartPrintManager" ); mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS); traceEnd(); } public void onStart () { publishBinderService(Context.PRINT_SERVICE, mPrintManagerImpl); } registerContentObservers(); registerBroadcastReceivers();
跟User关联的userState实例通过getOrCreateUserStateLocked方法创建并保存到 PMS的mUserStates中(userid–UserState map)
3. UserState 初始化
关联 RemotePrintSpooler类. 该类主要是讲远程打印机的状态本地化, 实现监控remote print的状态. (后台作业)
UserStateHandler, 用于处理
PRINT_JOB_STATE_CHANGED
/
PRINT_SERVICES_CHANGED
/
PRINT_SERVICES_RECOMMENDATIONS_UPDATED
CHECK_CONFIG_CHANGED
事件. 主要为前三类.
读取已经为该用户安装的printService插件. 满足几个条件:
manifest定义举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <service android:name="android.print.cts.services.FirstPrintService" 1. android:permission="android.permission.BIND_PRINT_SERVICE" > <intent-filter> 2. <action android:name="android.printservice.PrintService" /> </intent-filter> <meta-data 3. android:name="android.printservice" android:resource="@xml/printservice" > </meta-data> </service> <print-service xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="android.print.cts.services.SettingsActivity" android:addPrintersActivity="android.print.cts.services.AddPrintersActivity" android:advancedPrintOptionsActivity="android.print.cts.services.CustomPrintOptionsActivity" />
store the disabled services, 保存到表中 Settings.Secure.ENABLED_PRINT_SERVICES, 处理mDisabledServices
onConfigurationChangedLocked根据mDisabledServices和mActiveServices添加或删除打印插件托管,并通过MSG_DISPATCH_PRINT_SERVICES_CHANGED
回调IPrintServicesChangeListener的onPrintServicesChanged, 该listener通过*addPrintServicesChangeListener
*进行注册的.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public UserState (Context context, int userId, Object lock, boolean lowPriority) { mSpooler = new RemotePrintSpooler (context, userId, lowPriority, this ); mHandler = new UserStateHandler (context.getMainLooper()); synchronized (mLock) { readInstalledPrintServicesLocked(); upgradePersistentStateIfNeeded(); readDisabledPrintServicesLocked(); } prunePrintServices(); synchronized (mLock) { onConfigurationChangedLocked(); } }
需要重点看下onConfigurationChangedLocked函数的处理.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 private void onConfigurationChangedLocked () { ArrayList<ComponentName> installedComponents = getInstalledComponents(); final int installedCount = installedComponents.size(); for (int i = 0 ; i < installedCount; i++) { ComponentName serviceName = installedComponents.get(i); if (!mDisabledServices.contains(serviceName)) { if (!mActiveServices.containsKey(serviceName)) { RemotePrintService service = new RemotePrintService ( mContext, serviceName, mUserId, mSpooler, this ); addServiceLocked(service); } } else { RemotePrintService service = mActiveServices.remove(serviceName); if (service != null ) { removeServiceLocked(service); } } } Iterator<Map.Entry<ComponentName, RemotePrintService>> iterator = mActiveServices.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<ComponentName, RemotePrintService> entry = iterator.next(); ComponentName serviceName = entry.getKey(); RemotePrintService service = entry.getValue(); if (!installedComponents.contains(serviceName)) { removeServiceLocked(service); iterator.remove(); } } onPrintServicesChanged(); } 1.0 RemotePrintService的初始化+ mCallbacks = callbacks; + serviceName + userid + spooler + mPrintService 1.1 . 将该printService插件加到mActiveServices中1.2 . 回调mPrinterDiscoverySession onServiceAddedLocked (RemotePrintService) 方法private PrinterDiscoverySessionMediator mPrinterDiscoverySession; public void onServiceAddedLocked (RemotePrintService service) { if (mIsDestroyed) { Log.w(LOG_TAG, "Not updating added service - session destroyed" ); return ; } 1.2 .1 MSG_CREATE_PRINTER_DISCOVERY_SESSION 建立一个session mSessionHandler.obtainMessage( SessionHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION, service).sendToTarget(); 1.2 .2 通过session查找打印机 if (!mStartedPrinterDiscoveryTokens.isEmpty()) { mSessionHandler.obtainMessage( SessionHandler.MSG_START_PRINTER_DISCOVERY, service).sendToTarget(); } 1.2 .3 根据RemotePrintService 绑定的打印插件, 与搜索到的打印机, 打印机属于该打印插件时,启动tracking. final int trackedPrinterCount = mStateTrackedPrinters.size(); for (int i = 0 ; i < trackedPrinterCount; i++) { PrinterId printerId = mStateTrackedPrinters.get(i); if (printerId.getServiceName().equals(service.getComponentName())) { SomeArgs args = SomeArgs.obtain(); args.arg1 = service; args.arg2 = printerId; mSessionHandler.obtainMessage(SessionHandler .MSG_START_PRINTER_STATE_TRACKING, args) .sendToTarget(); } } } 2. removeServiceLocked private void removeServiceLocked (RemotePrintService service) { 2.1 failActivePrintJobsForService(service.getComponentName()); if (mPrinterDiscoverySession != null ) { 2.2 mPrinterDiscoverySession.onServiceRemovedLocked(service); } else { service.destroy(); } } 2.1 private void failScheduledPrintJobsForServiceInternal (ComponentName serviceName) { List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(serviceName, PrintJobInfo.STATE_ANY_SCHEDULED, PrintManager.APP_ID_ANY); if (printJobs == null ) { return ; } try { final int printJobCount = printJobs.size(); for (int i = 0 ; i < printJobCount; i++) { PrintJobInfo printJob = printJobs.get(i); mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED, mContext.getString(R.string.reason_service_unavailable)); } } finally { Binder.restoreCallingIdentity(identity); } } 2.2 . public void onServiceRemovedLocked (RemotePrintService service) { if (mIsDestroyed) { Log.w(LOG_TAG, "Not updating removed service - session destroyed" ); return ; } ComponentName serviceName = service.getComponentName(); removePrintersForServiceLocked(serviceName); 2.2 .1 service.destroy(); } 2.2 .1 private void handleDestroy () { stopTrackingAllPrinters(); if (mDiscoveryPriorityList != null ) { handleStopPrinterDiscovery(); } if (mHasPrinterDiscoverySession) { handleDestroyPrinterDiscoverySession(); } ensureUnbound(); mDestroyed = true ; }
3.1. 小节 该处主要涉及UserState的初始化. UserState是一个很重要的桥梁,关联到
RemotePrintService
每个RMS实例绑定到一个打印插件. UserState通过mActiveServices
保存了激活状态的RMS.通过mDisabledServices保存了弃用的RMS. RMS是以其绑定的打印插件compnent名为标志的. 当打印插件卸载时, 对应的RMS也要销毁. 当打印插件处于关闭状态时, RMS为Disable状态. 通过UserState的SessionHandler嫁接到RMS的handler中,并通过RMS的mPrintService控制打印插件进行真正的任务处理.
IPrinterDiscoveryObserver
(通过addObserverLocked添加)
该observer监听打印机的搜索过程, 这个地方主要关联到
frameworks /base /core /java /android /print /PrinterDiscoverySession.java
该类作为客户端,提供了setOnPrintersChangeListener方法, 通过observer的中转, 将打印机的状态变化可以通知到外部的app.
ex: Settings app
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 if (mDiscoverySession == null ) { PrintManager printManager = (PrintManager) getContext() .getSystemService(Context.PRINT_SERVICE); new AsyncTask <Void, Void, Void>() { @Override protected Void doInBackground (Void... params) { mDiscoverySession = printManager.createPrinterDiscoverySession(); return null ; } @Override protected void onPostExecute (Void result) { if (mDiscoverySession == null ) { return ; } mDiscoverySession.setOnPrintersChangeListener(new OnPrintersChangeListener () { @Override public void onPrintersChanged () { deliverResult(new ArrayList <PrinterInfo>( mDiscoverySession.getPrinters())); } }); mDiscoverySession.startPrinterDiscovery(null ); } }.execute(); }
IPrintServicesChangeListener
(通过addPrintServicesChangeListener添加)通过PrintManager中转,提供给外部app使用. 通知RMS状态的变更. 外部可以通过mPrintManager.getPrintServices拿到打印插件.
1 2 3 4 5 List<PrintServiceInfo> infos = mPrintManager.getPrintServices( PrintManager.ENABLED_SERVICES); addPrintServicesChangeListener mPrintManager.addPrintServicesChangeListener(this , null );
RemotePrintSpooler
bind到后台作业服务, “com.android.printspooler”
源码中默认为PrintSpooler frameworks/base/packages/PrintSpooler/
通过setClientLocked设置PrintSpoolerClient为PrintSpooler的client.
PrintSpoolerClient 类通过callbacks 实际传导到userState类中, userState再根据消息类别转发到不同的地方进行处理.
1 2 3 public static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler" ;mIntent.setComponent(new ComponentName (PrintManager.PRINT_SPOOLER_PACKAGE_NAME, PrintManager.PRINT_SPOOLER_PACKAGE_NAME + ".model.PrintSpoolerService" ));
以restartPrintJob为例. 说明下调用流程. (app调用PrintManager的接口)
PrintManager –> PrintManagerService –> UserState
– > RemotePrintSpooler –> RPS.SetPrintJobStateCaller–> PrintSpooler.PrintSpoolerService
– setPrintJobState –> PrintSpooler.PrintSpoolerService – sendOnPrintJobQueued –> mClient.onPrintJobQueued(printJob);
回调过程:
PrintSpoolerClient
.onPrintJobQueued –> UserState
–onPrintJobQueued–> RemotePrintService.onPrintJobQueued–> 打印插件服务
– onPrintJobQueued
可见有最终任务的还是要通过打印插件服务传递给打印机.
4. 系统内建打印插件服务 BuiltInPrintService
packages /services /BuiltInPrintService /
4.1. Manifest 解释 1 2 3 <service android:name="com.android.bips.BuiltInPrintService" <service android:name="com.android.bips.render.PdfRenderService" android:name="com.android.bips.ui.AddPrintersActivity"
1 2 3 4 <print-service xmlns:android ="http://schemas.android.com/apk/res/android" android:addPrintersActivity ="com.android.bips.ui.AddPrintersActivity" />
服务插件需要继承 PrintService
1 public class BuiltInPrintService extends PrintService {
继承的方法:
onCreatePrinterDiscoverySession
onRequestCancelPrintJob(PrintJob printJob)
onPrintJobQueued(PrintJob printJob)
4.2. PrintService 基类 PrintService是RemotePrintService bind的基类, RMS中保存的mPrintService指向该类
成员:
mClient
指向RemotePrintService的内部类RemotePrintServiceClient.
该变量被传到PrintJob的mPrintServiceClient中.
mDiscoverySession
通过子类实现的onCreatePrinterDiscoverySession的方法创建.
为PrinterDiscoverySession对象. 需要打印服务插件继承该类.提供打印插件内打印机搜索跟踪打印机状态等的功能.
4.3. PrinterDiscoverySession基类 服务插件的Session类需要继承PrinterDiscoverySession
需继承的方法:
onStartPrinterDiscovery(@NonNull List priorityList)
onStopPrinterDiscovery()
onValidatePrinters(@NonNull List printerIds)
onStartPrinterStateTracking(@NonNull PrinterId printerId)
onRequestCustomPrinterIcon
onStopPrinterStateTracking
onDestroy
5. Ui 显示 系统中内置的加载printer的显示为Settings进程.
packages /apps /Settings /src /com /android /settings /print /
PrintServiceSettingsFragment.java
涉及到LOADER的使用:
1 2 3 4 5 6 7 public class PrintServiceSettingsFragment extends SettingsPreferenceFragment implements SwitchBar .OnSwitchChangeListener, LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> { private final class PrintersAdapter extends BaseAdapter implements LoaderManager .LoaderCallbacks<List<PrinterInfo>>, Filterable {
5.1. Loader Loader在执行了startLoading()方法后,会进入started状态,LoaderManager会在合适的时机执行Loader.startLoading()方法,概括来说,当我们执行LoadManager.initLoader()时,如果Loader不存在,内部会执行LoadCallbacks的onCreateLoader()方法创建Loader,并让新创建的Loader执行startLoading()方法。
具体执行过程如下: LoaderManager.initLoader() -> LoaderManager.createAndInstallLoader() -> LoaderManager.createLoader() ->LoaderCallbacks.onCreateLoader()
-> 得到loader之后创建LoaderInfo -> LoaderManager.installLoader() -> 将其放入LoaderManager内部维护的mLoaders数组中 -> LoaderInfo.start() -> Loader处于started状态 ->Loader.startLoading() ->Loader.onStartLoading()
5.2. LoaderManager.LoaderCallbacks LoaderManager.LoaderCallbacks是LoaderManager中的内部接口,客户端与Loader的通信完全是事件机制,即客户端需要实现LoaderCallbacks中的各种回调方法,以响应Loader & LoaderManager触发的各种事件。客户端在调用LoaderManager的initLoader
()或restartLoader
()方法时,就需要客户端向这两个方法中传入一个LoaderCallbacks的实例。LoaderCallbacks有三个回调方法需要实现:onCreateLoader()、onLoadFinished()以及onLoaderReset()。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class PrintServiceSettingsFragment extends SettingsPreferenceFragment implements SwitchBar .OnSwitchChangeListener, LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> { getLoaderManager().initLoader(LOADER_ID_PRINT_SERVICE_LOADER, null , this ); @Override public Loader<List<PrintServiceInfo>> onCreateLoader (int id, Bundle args) { return new PrintServicesLoader ( (PrintManager) getContext().getSystemService(Context.PRINT_SERVICE), getContext(), PrintManager.ALL_SERVICES); } private final class PrintersAdapter extends BaseAdapter implements LoaderManager .LoaderCallbacks<List<PrinterInfo>>, Filterable { public void enable () { getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null , this ); } @Override public Loader<List<PrinterInfo>> onCreateLoader (int id, Bundle args) { if (id == LOADER_ID_PRINTERS_LOADER) { return new PrintersLoader (getContext()); } return null ; }
5.3. onCreateLoader onCreateLoader:我们要在onCreateLoader()方法内返回一个Loader的实例对象。很多情况下,我们需要查询ContentProvider里面的内容,那么我们就需要在onCreateLoader中返回一个CursorLoader的实例,CursorLoader继承自Loader。
如果CursorLoader不能满足我们的需求,我们可以自己编写自己的Loader然后在此onCreateLoader方法中返回。
此处是自己构造的loader
1 public class PrintServicesLoader extends Loader <List<PrintServiceInfo>>
此处返回的是Loader<List>, 是PrintServicesLoader对象.
PrintServiceInfo是关联到安装的打印插件服务的. PrintServiceInfo中保存了打印服务插件的从PackageManager拿到的resolveInfo信息(queryIntentServicesAsUser返回的结果)和前面介绍的settingsActivityName/addPrintersActivityName/advancedPrintOptionsActivityName
1 2 3 4 tempPrintServices.add(PrintServiceInfo.create(mContext, installedService)); mInstalledServices.addAll(tempPrintServices);
1 2 3 4 5 6 7 8 public PrintServicesLoader (@NonNull PrintManager printManager, @NonNull Context context, int selectionFlags) { super (Preconditions.checkNotNull(context)); mHandler = new MyHandler (); mPrintManager = Preconditions.checkNotNull(printManager); mSelectionFlags = Preconditions.checkFlagsArgument(selectionFlags, PrintManager.ALL_SERVICES); }
onForceLoad
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @Override protected void onForceLoad () { queueNewResult(); } private void queueNewResult () { Message m = mHandler.obtainMessage(0 ); 1. m.obj = mPrintManager.getPrintServices(mSelectionFlags); mHandler.sendMessage(m); } private class MyHandler extends Handler { public MyHandler () { super (getContext().getMainLooper()); } @Override public void handleMessage (Message msg) { if (isStarted()) { 2. 通知loader更新,回调LoadCallbacks.onLoadFinished() deliverResult((List<PrintServiceInfo>) msg.obj); } } }
在回调onPrintServiceChanged时也进行更新
1 2 3 4 5 6 7 mListener = new PrintManager .PrintServicesChangeListener() { @Override public void onPrintServicesChanged () { queueNewResult(); } }; mPrintManager.addPrintServicesChangeListener(mListener, null );
我们可以在onStartLoading()中写我们的逻辑,在started状态下,Loader应该监控数据源的变化,并将新数据发送给客户端,具体来说就是当监控到新数据后,调用Loader.deliverResult()方法,触发LoadCallbacks.onLoadFinished()回调的执行,从而客户端可以从该回调中轻松获取数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public void onLoadFinished (Loader<List<PrintServiceInfo>> loader, List<PrintServiceInfo> services) { if (services != null ) { final int numServices = services.size(); for (int i = 0 ; i < numServices; i++) { if (services.get(i).getComponentName().equals(mComponentName)) { service = services.get(i); break ; } } } 1. mServiceEnabled = service.isEnabled(); 2. ... 3. updateUiForServiceState() 3. private void updateUiForServiceState () { if (mServiceEnabled) { mSwitchBar.setCheckedInternal(true ); mPrintersAdapter.enable(); } else { mSwitchBar.setCheckedInternal(false ); mPrintersAdapter.disable(); } getActivity().invalidateOptionsMenu(); } 3.1 mPrintersAdapter.enable(); public void enable () { getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null , this ); }
在最后调用了PrintAdapter的initLoader方法, 该方法会触发onCreateLoader的回调.PrintAdapter对应的Loader为PrintersLoader类.
1 2 3 4 5 6 7 @Override public Loader<List<PrinterInfo>> onCreateLoader (int id, Bundle args) { if (id == LOADER_ID_PRINTERS_LOADER) { return new PrintersLoader (getContext()); } return null ; }
PrintersLoader重写了Loader中的onStartLoading()方法,以下是PrintersLoader在执行到onStartLoading()之后的逻辑,从中我们可以看出PrintLoader如何实现异步加载打印机数据。
在onForceLoad中执行了AsyncTask启动startPrinterDiscovery进行搜索搜索打印插件关联的打印机, 在搜索到打印机后,由callback机制, 回调注册的OnPrintersChangeListener的onPrintersChanged方法, 通过deliverResult触发LoaderCallbacks的onLoadFinished方法, 再通过notifyDataSetChanged方法使得视图更新.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 @Override protected void onStartLoading () { if (DEBUG) { Log.i(LOG_TAG, "onStartLoading()" ); } if (!mPrinters.isEmpty()) { 2. deliverResult(new ArrayList <PrinterInfo>(mPrinters.values())); } 1. onForceLoad(); } 1. protected void onForceLoad () { loadInternal(); } private void loadInternal () { if (mDiscoverySession == null ) { PrintManager printManager = (PrintManager) getContext() .getSystemService(Context.PRINT_SERVICE); new AsyncTask <Void, Void, Void>() { @Override protected Void doInBackground (Void... params) { mDiscoverySession = printManager.createPrinterDiscoverySession(); return null ; } @Override protected void onPostExecute (Void result) { mDiscoverySession.setOnPrintersChangeListener(new OnPrintersChangeListener () { @Override public void onPrintersChanged () { deliverResult(new ArrayList <PrinterInfo>( mDiscoverySession.getPrinters())); } }); mDiscoverySession.startPrinterDiscovery(null ); } }.execute(); } 2. public void onLoadFinished (Loader<List<PrinterInfo>> loader, List<PrinterInfo> printers) { synchronized (mLock) { mPrinters.clear(); final int printerCount = printers.size(); for (int i = 0 ; i < printerCount; i++) { PrinterInfo printer = printers.get(i); if (printer.getId().getServiceName().equals(mComponentName)) { mPrinters.add(printer); } } mFilteredPrinters.clear(); mFilteredPrinters.addAll(mPrinters); if (!TextUtils.isEmpty(mLastSearchString)) { getFilter().filter(mLastSearchString); } } notifyDataSetChanged(); }
5.4. destroyLoader 在由PrintServiceLoader注册的addPrintServicesChangeListener回调流程中,在检测到PrintService change时, 最终触发下面的流程.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private void updateUiForServiceState () { if (mServiceEnabled) { mSwitchBar.setCheckedInternal(true ); mPrintersAdapter.enable(); } else { mSwitchBar.setCheckedInternal(false ); 1. mPrintersAdapter.disable(); } getActivity().invalidateOptionsMenu(); } 1. public void disable () { getLoaderManager().destroyLoader(LOADER_ID_PRINTERS_LOADER); mPrinters.clear(); }
LoaderManager.destroy() –>
LoaderCallbacks
.onLoaderReset() –>
Loader.reset() –>
PrintLoader.onReset()–>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @Override public void onLoaderReset (Loader<List<PrinterInfo>> loader) { synchronized (mLock) { mPrinters.clear(); mFilteredPrinters.clear(); mLastSearchString = null ; } notifyDataSetInvalidated(); } @Override protected void onReset () { if (DEBUG) { Log.i(LOG_TAG, "onReset()" ); } 1. onStopLoading(); mPrinters.clear(); if (mDiscoverySession != null ) { 2. mDiscoverySession.destroy(); mDiscoverySession = null ; } } 1. protected void onStopLoading () { if (DEBUG) { Log.i(LOG_TAG, "onStopLoading()" ); } onCancelLoad(); } protected boolean onCancelLoad () { if (DEBUG) { Log.i(LOG_TAG, "onCancelLoad()" ); } return cancelInternal(); } private boolean cancelInternal () { if (mDiscoverySession != null && mDiscoverySession.isPrinterDiscoveryStarted()) { 1.1 mDiscoverySession.stopPrinterDiscovery(); return true ; } return false ; }