设为首页 收藏本站
查看: 1029|回复: 0

[经验分享] 学习Android最核心的Context主板模式

[复制链接]

尚未签到

发表于 2017-3-1 09:01:12 | 显示全部楼层 |阅读模式
  By 高焕堂   
  
学习Android最核心的Context主板模式

1.  认识AndroidContext主板模式
   我们从典型的主板模式(MB pattern)出发,来了解Android的Context主板模式设计。于是,架构师心中有个Context接口,并且设计一个抽象父类来实现(Implement)该接口,如下图:

               DSC0000.jpg
      这就是典型的软件主板了。如下图所示:

          DSC0001.jpg
     由于接口就是一种退化型的<类>。所以上图里的接口,可以定义于一个类之中,成为一个<接口类>。于是此<接口类>及其<实现类>,就组合成为一个软件主板了。如下图:

          DSC0002.jpg
    此时,<E>的operation()函数可以去调用IE_Impl类里的operation()函数,执行其实现代码了,它(即<E>)的operation()函数就不必重复撰写operation()函数的实现代码了。这项途径,在软件设计上称为”委托”(Delegation)。也可以将IE_Impl类独立出来,如下图所示:
            DSC0003.jpg
    本来是<E>类必须撰写operation()函数的实现代码,为了避免重复撰写实现代码,<E>类就就转而”委托”IE_Impl类,调用它的operation()实现代码。这种架构设计的效益是,<E>类不必再重复撰写operation()函数的实现代码,可节省开发、维护实现代码的负担。当<E>类的个数愈多时,这种架构设计的效益就愈大。如下图所示:

      图里的黑色菱形符号(◆)表示<E>类都会创建一个IE_Impl类的对象,然后<E>类的operation()函数会调用IE_Impl类的operation()的实现代码。也就是,<E>类将它自己的operation()函数的实现工作委托给IE_Impl类去做了。
   
2. Android的Context通用性接口
      在Android框架里,俗称”慈禧太后”的至高权力Context接口,就依循上一小节所叙述的架构,其的详细内涵如下图:
    DSC0004.jpg
     这个Context通用性接口,是Android框架里最具有权力地位的接口。例如,只要你能取得这个Context接口,就能调用极具权力象征的startActivity()函数。
DSC0005.jpg
    从上图可以看到,除了startActivity()函数之外,还有startService()函数、bindService()函数等,都是Android平台上最常用的函数。在Android里,上图的实现代码片段如下:
public class ContextWrapper extends Context {
     Context mBase;
     public ContextWrapper(Context base) {
         mBase = base;
     }
    //………
    @Override public void startActivity(Intent intent) {
           mBase.startActivity(intent);
      }
     @Override public ComponentName startService(Intent service) {
           return mBase.startService(service);
      }
     //………
}
    其中,mBase是指针,用来指向ContextImpl对象的Context接口。也就是说,ContextWrapper对象都会含有一个ContextImpl对象的指针。这让ContextWrapper能透过mBase而调用ContextImpl类里的实现代码。例如,
    public void startActivity(Intent intent) {
           mBase.startActivity(intent);
      }
就是”委托”(Delegation)机制的实际运行了。

class ContextImpl extends Context {
//...........
@Override public void startActivity(Intent intent) {
        warnIfCallingFromSystemProcess();
        startActivity(intent, null);
    }
@Override
public void startActivity(Intent intent, Bundle options) {
         // 实现代码
    }
//………
@Override
public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceAsUser(service, mUser);
    }
@Override
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
       // 实现代码
    }   
    // ……..
}

3.  举例说明Context通用性接口的应用
      在Android框架里,这俗称为”慈禧太后”至高权力的Context接口,其结构,也可以表示如下:
    DSC0006.jpg
    无论是Android手机或是PC等其它设备,皆能透过HTTP来呼叫你手机上的Servlet(如执行于i-Jetty内),然后该Servlet进而呼叫同一支手机内的Android应用程序或服务。
   DSC0007.jpg
    这i-Jetty本身是以Android应用程序形式嵌入(运行)于Android平台里,它可以透过Android框架的API与其它应用程序沟通。因而,在i-Jetty里执行的Servlet程序也能透过该Android API而与其它应用程序沟通、分享数据。例如,在家庭的Android TV里,加入一个i-Jetty插件,来容纳HTML网页和Servlet程序。数千公里外的家庭成员,透过手机Browser解析HTML,与家里的TV沟通,形成大小屏互动、多机整合的架构设计了。
DSC0008.jpg
       I-Jetty是一支Android应用程序(*.apk),其扮演Container角色,让许多支Servlet程序可以在Android手机里执行。然而,这些Servlet程序经常需要与同一只手机里的其它Android应用程序沟通,例如启动晨钟或闹铃等等。此时,只要能取得Android框架的Context接口,就能呼叫Android的服务了。这个Context界面位居幕后,仅从应用程序代码的表面,常常看不到,然而它却是Android平台框架的最主要服务窗口。Context接口提供数十个大家很常用的服务,例如startService()、sendBroadcast()函数等。
    由于Activity也是继承Context抽象父类别,意味着Activity也是实作(Implements)这个Context界面。所以我们在Android应用程序里(如myActivity子类别)随时可呼叫Context接口里的函数,如下述的程序范例:

// Android程序范例
//.........
public class ac01 extends Activity implements OnClickListener {
       private Button btn, btn3;
       @Override protected void onCreate(Bundle icicle) {
             super.onCreate(icicle);
             //…….
             setContentView(layout);
        }
      public void onClick(View v) {
            if(v == btn)  
                   startService(new Intent(this, myService.class));
            else if(v == btn3)   
                   finish();
  }}
其中的指令: startService(new Intent(this, myService.class));
相当于指令: this.startService(new Intent(this, myService.class));
意味着,其呼叫到Context接口的startService()函数。其幕后机制是,myActivity类别呼叫到ContextWrapper类别的Context接口(的startService()函数),然后转而呼叫其mBase的(例如ApplicationContext的对象)Context接口的startService()函数。除了startService()函数之外,Context接口还含有许多其它函数,例如getApplicationContext()函数等。

手机内的I-Jetty与Android沟通
     同理,我们撰写i-Jetty里的myServlet程序时,也能透过Context接口来呼叫startService()函数来启动Android应用程序里的myService子类别,也能呼叫Context接口startActivity()函数来启动Android应用程序里的myActivity子类别,如下图:
DSC0009.jpg
  (Context接口扮演Android云端整合的重要接口)
      在myServlet子类别里可利用指令:
                  config.getServletContext().getAttribute("org.mortbay.ijetty.context");
指令来取得其当下的Context接口,如下述i-Jetty的范例程序代码:

/* --- i-Jetty的Servlet程序范例 ----*/
/**** 摘自i-Jetty套件的范例 ****/
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld extends HttpServlet {
     String proofOfLife = null;
     public void init(ServletConfig config) throws ServletException {
             super.init(config);
             Object o =
                  config.getServletContext().getAttribute("org.mortbay.ijetty.contentResolver");
             android.content.ContentResolver resolver
                  = (android.content.ContentResolver)o;
             android.content.Context androidContext
                 = (android.content.Context) config.getServletContext().getAttribute("org.mortbay.ijetty.context");
             proofOfLife = androidContext.getApplicationInfo().packageName;
  }
  public void doPost(HttpServletRequest request, HttpServletResponse response)
                          throws ServletException, IOException
        {  doGet(request, response);   }
  public void doGet(HttpServletRequest request, HttpServletResponse response)
                         throws ServletException, IOException {
        response.setContentType("text/html");
        ServletOutputStream out = response.getOutputStream();
        out.println("<html>");
        out.println("<h1>Hello From Servlet Land!</h1>");
        out.println("Brought to you by: "+proofOfLife);
        out.println("</html>");
        out.flush();
    }
}

I-Jetty与Android的跨手机沟通
   上图里是从同一支手机(本机)里的myActivity来呼叫本机的Servlet接口,这是可行的,但是意义比较小。更大的意义是:由别的手机里的myActivity来传送HTTP呼叫到本机的Servlet接口,呼叫到本机的myServlet子类别;然后由myServlet呼叫Android的Context接口,而完成两支手机里两个myActivity子类别之间的相互沟通。如下图:
DSC00010.jpg
(两支手机之通讯)
       于是,Context和Servlet两大接口,成为Android**云的喜鹊桥的两个主要桥墩。◆
  [Go Back]

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-348587-1-1.html 上篇帖子: 使用 sbt 0.11 JRebel 构建 Lift2.4 应用 下篇帖子: HTTP2 学习
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表