美文网首页
以DownLoadManager为例说一说关于阅读代码

以DownLoadManager为例说一说关于阅读代码

作者: 浮华的人 | 来源:发表于2016-06-21 21:59 被阅读68次

    当我们要去看一个陌生的项目的时候,经常会遇到很多类,很烦恼,感觉就像是一片又一片的森林走不到头,然后就会产生烦躁的思想,但是我们都知道,跟着一条主线往下走,我也是这个样子但是还是经常会把自己绕进去。

    看代码,或者说学习别人的代码,怎么才算完全懂了?
    对于细读代码我觉的下面这些是必要的:

    理清楚业务逻辑,不要只是一个方法名一个方法名的向下去追。那么这就要求我们看清楚的这个对象是在那里创建的,这个方法是运行在哪个进程的那个线程里面。关注这个对象是在什么地方new出来的,这个方法的参数是在什么地方创建出来的。一定注意揣摩方法名和变量名的意思,不要图快,多去读注释,理解写代码的人想表达的意思。停下来对思考它这个地方为什么要这样写,如果是你你怎么写,去分析代码的业务是怎样的,都要处理那几种情况,多给自己提出问题,从code中去思考答案,多回头,记住阅读前面的代码遇到的问题,在阅读完后面的代码之后,在从全局的角度去思考这个问题,考虑他为什么这样写。

    我认为呢? 首先,牢记我们的目的是什么?理清楚一个方法,变量,功能还是什么的。每一次深入都结合目的思考一下,这样子不容易走丢。接下来我认为的最重要的一点,看接口和抽象类,我认为不管是多复杂的项目,只要我们能,把它的继承关系,理清楚,看到哪里都不会丢,我们知道好的项目他的代码都会做好分层,做好解耦,也就是面向接口编程应用的很好,以前看设计模式,对面向对象6大原则,只是在能读懂的阶段,远没有达到能在代码设计阶段就将他们体现的淋漓尽致,而好的项目源码,他的架构脉络应该是清晰的,也就是抽象类和接口,对于设计模式有很好的应用,我一直认为,抽象的好的话,那么架构就不会太差。

    所以再看代码的时候,我认为还应该看清接口的依赖,理清楚回调,一个项目差不多就能想看哪里看哪里了。

    下面分享我对android downloadmanager学习,

    public long enqueue(Request request) {
    
    ContentValues values = request.toContentValues(mPackageName);
    
    Uri downloadUri = mResolver.insert(Downloads.Impl.CONTENT_URI, values);
    
    long id = Long.parseLong(downloadUri.getLastPathSegment());
    
    return id;
    
    }
    

    这个方法很简单,也很重要,封装一个请求,添加到数据库,这里为什么要添加到数据库呢,直接处理不行吗?考虑业务场景,我们在“下载”这个应用里面是不是可以看到自己的下载记录,还可以管理,那这样是不是就有存到数据库的必要了。返回一个id,后面可以通过这个id来,简单的维护一下我们的请求,
    那么问题又来了这里只是添加了数据库,系统怎么知道我们要下载东西呢?
    熟悉contentprovider的同学都知道,contentprovider可以把数据库的改动通知给关注某个uri的应用。
    那么我们如何去找真正的下载的code在哪呢?
    我们注意看上买呢insert方法后面跟的那个静态的uri,从这个uri我们就可以找到对应的contentprovider是DownloadProvider,观察这个类我们发现它继承自DocumentsProvider不知道有没有同学用过这个东西呢?提醒以下这个东西在apiguide里面又讲哦!

    insertRequestHeaders(db, rowID, values);
    notifyContentChanged(uri, match);
    // Always start service to handle notifications and/or scanningfinal 
    Context context = getContext();
    context.startService(new Intent(context, DownloadService.class));
    

    ok在downloadProvider的insert方法的最下面我们发现了这样的代码,很明显这里会通知,而且还启动了接受通知的服务,从注释也能肯出来这一点。那么下来我们就来看一下这个服务。

    /** * Initializes the service when it is first created */
    @Override
    public void onCreate() {   
     super.onCreate();   
     if (Constants.LOGVV) {    
        Log.v(Constants.TAG, "Service onCreate");    
    }  
      if (mSystemFacade == null) {    
        mSystemFacade = new RealSystemFacade(this);  
      }  
    //用到这个要做定时任务,猜想?
      mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
    //推测这是网络下载应该是在这个线程里面进行   
    mUpdateThread = new HandlerThread(TAG + "-UpdateThread");    
    mUpdateThread.start();  
      mUpdateHandler = new Handler(mUpdateThread.getLooper(), mUpdateCallback);   
    //扫描? 
    mScanner = new DownloadScanner(this);  
    //通知,这个应该不会错了  
    mNotifier = new DownloadNotifier(this);   
     mNotifier.cancelAll();  
    //观察者,观察数据库的变化,从那个uri也可以看出
      mObserver = new DownloadManagerContentObserver();    
    getContentResolver().registerContentObserver(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, true, mObserver);   
    //不知道有没有小伙伴用过这个。
    JobScheduler js = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);    if (needToScheduleCleanup(js)) {        final JobInfo job = new JobInfo.Builder(CLEANUP_JOB_ID, sCleanupServiceName)                .setPeriodic(CLEANUP_JOB_PERIOD)                .setRequiresCharging(true)                .setRequiresDeviceIdle(true)                .build();        js.schedule(job); 
       }}
    

    ok以上就是DownService的oncreate方法了,看完也能猜测一部分代码吧。
    以为这是一个服务嘛,所以呢我们继续去看剩余的生命周期方法,在onstartcommand调用了这个方法我们继续看。

    public void enqueueUpdate() { 
       if (mUpdateHandler != null) {        
        mUpdateHandler.removeMessages(MSG_UPDATE);        
        mUpdateHandler.obtainMessage(MSG_UPDATE, mLastStartId, -1).sendToTarget();
        }}
    

    我们继续去读那个handler,
    果然 DownloadService有这麽个观察者,downloaservice这个类我们只看他的下载流程,现在不要在意细节,在oncreate里初始化handler ,而上面观察到数据变化,会发送消息,然后会掉updateLocked()这个方法来查询数据库,拿出请求封装成了一个downloadinfo ,在这类里面有这个方法info.startDownloadIfReady(mExecutor); 见名知意。进去看我们发现他们任务都扔到线程池里面去处理了,当然还有DownloadThread这个类,处理之前是先把请求封装成这个线程的。

    ok这就是大概的一个流程,写的有点乱,在这个基础上再来看download的细节就会很轻松了。

    相关文章

      网友评论

          本文标题:以DownLoadManager为例说一说关于阅读代码

          本文链接:https://www.haomeiwen.com/subject/azmgdttx.html