溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

框架如何創(chuàng)建App子類的對象(二)?

發(fā)布時間:2020-06-02 08:32:39 來源:網(wǎng)絡(luò) 閱讀:546 作者:myeit 欄目:移動開發(fā)

前言:

誰來誕生子類的對象呢? 答案是:框架。這樣讓框架能有絕對的制約能力去「框住」應(yīng)用子類的結(jié)構(gòu)和行為。接著,請你來思考一個有趣的問題:

l框架開發(fā)者(強龍)先寫框架基類的程序碼;

l然后,AP開發(fā)者(地頭蛇)才撰寫應(yīng)用子類在后。

那么框架開發(fā)者事先又如何知道地頭蛇后來撰寫的應(yīng)用子類的名稱呢? 如果不知道應(yīng)用子類的名稱,又如何誕生應(yīng)用子類的對象呢?

框架如何創(chuàng)建App子類的對象(二)?

ee                                                                        ee

歡迎訪問 ==>高老師的博客網(wǎng)頁

高煥堂:MISOO(大數(shù)據(jù).大思考)聯(lián)盟.臺北中心和東京(日本)分社.總教練


EE                                                                        EE

框架如何創(chuàng)建App子類的對象(二)?

--- 由基類創(chuàng)建親生子類的對象  


1.  以MediaPlayer播放mp3音樂為例

大家對于拿MediaPlayer來播放mp3音樂的應(yīng)用程序,應(yīng)該不會陌生。最簡單的架構(gòu)如下圖所示:

框架如何創(chuàng)建App子類的對象(二)?

圖1、由myActivity來創(chuàng)建MediaPlayer的對象

你也可以設(shè)計一個包容器(Wrapper)類別來包裝MediaPlayer類別,也就是由這個Wrapper來幫忙創(chuàng)建MediaPlayer對象,如下圖所示:

框架如何創(chuàng)建App子類的對象(二)?

圖2、由Wrapper協(xié)助來創(chuàng)建MediaPlayer的對象

無論是在上圖1或圖2的架構(gòu)里,你都是扮演一個傳統(tǒng)的角色:AP開發(fā)者。于此,就來換個新鮮的角色:框架開發(fā)者。在上一篇文章里,已經(jīng)說明了,必須讓框架基類去創(chuàng)建應(yīng)用子類的對象,才能讓框架擁有高度的制約力量。在上一篇文章的范例里(即Ex04_01程序范例)已經(jīng)實踐了這個目標,讓框架基類(如GraphView)來創(chuàng)建子類別(如myDrawing)的對象。其中,值得留意的是:上一篇文章范例里的基類GraphView并不是myDrawing的直系父類別(基類)。簡而言之,myDrawing并不是繼承GraphView基類。亦即,myDrawing并不是GraphView的親生應(yīng)用子類。

   于是,在本文里,我們來看看一個基類如何創(chuàng)建親生子類別的對象。如下圖所示:

框架如何創(chuàng)建App子類的對象(二)?

圖3、由基類Player來創(chuàng)建親生子類mp3Player的對象

     大家都知道一個類別本身就是一個對象,我們常常稱之為「母對象」(Meta-object),而類別的靜態(tài)函數(shù)(static function)就是這個母對象的函數(shù),在這種函數(shù)里可以(由該母對象)創(chuàng)建自己類別的對象。在上圖的架構(gòu)里,由myActivity創(chuàng)建Player基類的init()靜態(tài)函數(shù),這init()創(chuàng)建其親生子類別mp3Player的對象。請留意,這init()會將mp3Player的IPlay接口傳回給myActivity。一旦myActivity接到mp3Player的IPlay接口,就能進行實際的創(chuàng)建動作。也就是,myActivity透過IPlay接口,而創(chuàng)建到mp3Player的play()函數(shù),并進而創(chuàng)建MediaPalyer的start()函數(shù),展開了播放mp3音樂的動作了。[歡迎光臨 高煥堂 網(wǎng)頁: http://www.cnblogs.com/myEIT/ ]

2.  框架的設(shè)計與實踐

2.1 復(fù)習:擅用配置文文件

   在上一篇文章里,運用了配置(Configuration)文件的機制來實踐由框架(的基類)來創(chuàng)建應(yīng)用(AP或App)子類的對象的任務(wù),這是框架開發(fā)的基本技巧。其主要面對的情境是:框架基類由強龍設(shè)計在先,而應(yīng)用子類則由地頭蛇開發(fā)在后。也就是說,當強龍撰寫框架基類時,地頭蛇(和客戶)都尚未出現(xiàn),基類開發(fā)者還不知道AP子類的名稱,那么又如何去<<new>>一個AP子類的對象呢? 其實很簡單,因為在程序的執(zhí)行時間( Run-time)才會真正創(chuàng)建對象,這執(zhí)行時間已經(jīng)是在地頭蛇撰寫子類的時間之后了,如下圖所示:

框架如何創(chuàng)建App子類的對象(二)?

圖4、由子類開發(fā)者撰寫配置(Configuration)文件

  因此,解決之道是:請地頭蛇撰寫完AP子類時,也將子類的名稱字符串(classname string)寫入一個特定的配置(Configuration)文件里,然后于程序執(zhí)行時,才去讀取配置文文件里的子類的名稱字符串,然后透過Java的指令:

Class.forName(classname).newInstance();

就能創(chuàng)建該AP子類的對象了。于是,實踐了由框架創(chuàng)建AP子類對象的任務(wù)了。

2.2 設(shè)計架構(gòu)圖

基于上述配置文文件的機制,也依循上一篇文章范例的架構(gòu),茲繪制架構(gòu)圖如下:

框架如何創(chuàng)建App子類的對象(二)?

圖6、由基類創(chuàng)建子類對象的過程

創(chuàng)建完成子類對象之后,就能夠透過接口來調(diào)用該子類對象的函數(shù)了。例如,myActivity就透過IPlay而調(diào)用mp3Player的play()函數(shù),此刻myActivity就調(diào)用MediaPlayer的start()函數(shù),開始播放了。如下圖:

框架如何創(chuàng)建App子類的對象(二)?

圖7、調(diào)用所創(chuàng)建的新對象

結(jié)束播放時,myActivity就透過IPlay而調(diào)用了mp3Player的stop()函數(shù),此刻myActivity就調(diào)用MediaPlayer的stop()函數(shù)了。

2.3  撰寫代碼:<創(chuàng)建對象>的實踐途徑

茲將上圖落實為Android代碼,其執(zhí)行畫面如下:

框架如何創(chuàng)建App子類的對象(二)?

首先建立一個Android的Ex04_02項目(Project),如下:

框架如何創(chuàng)建App子類的對象(二)?

背景圖像sunrise.png存在/res里。

  • 撰寫你的框架基類和API

// Player.java

package myFramework;

import android.content.Context;

public abstract class Player {

      static private Player player = null;

public static IPlay init(Context context){

               String pkclassName = ((PActivity)context).getPlayerClass();

               try {

                      player = (Player)Class.forName(pkclassName).newInstance();

                      return (IPlay)player;

                    } catch (Exception e)

                           { e.printStackTrace();  }

              return null;

          }

}

// PActivity.java

package myFramework;

import com.misoo.pk003.R;

import android.app.Activity;

public abstract class PActivity extends Activity{

      public IPlay init(){

            return Player.init(this);

       }

      public String getPlayerClass(){

               return this.getResources().getString(R.string.playerclass);

     }

}

//  IPlay.java

package myFramework;

import android.content.Context;

public interface IPlay {

   void play(Context context);

   void stop();

}

  • 把基類和API送人,協(xié)助別人去開發(fā)應(yīng)用子類

// mp3Player.java

package com.misoo.pk003;

import myFramework.IPlay;

import myFramework.Player;

import android.content.Context;

import android.media.MediaPlayer;

import android.util.Log;

public class mp3Player extends Player implements IPlay{

private MediaPlayer mPlayer = null;

public void play(Context context) {

    try{

           mPlayer = MediaPlayer.create(context, R.raw.dreamed);

           mPlayer.start();

          } catch (Exception e) {

                Log.e("StartPlay", "error: " + e.getMessage(), e);

             }

       }

public void stop(){

     if (mPlayer != null) {

          mPlayer.stop();      mPlayer.release();         mPlayer = null;

      }

 }}

// myActivity.java

package com.misoo.pk003;

import myFramework.IPlay;

import myFramework.PActivity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.LinearLayout;


public class myActivity extends PActivity implements OnClickListener{

private Button ibtn1, ibtn2;

private IPlay player;

@Override protected void onCreate(Bundle icicle) {

       super.onCreate(icicle);

       LinearLayout layout = new LinearLayout(this);

       layout.setOrientation(LinearLayout.VERTICAL);

       ibtn1 = new Button(this);        ibtn1.setOnClickListener(this);

       ibtn1.setText("Play");              ibtn1.setBackgroundResource(R.drawable.heart);

       LinearLayout.LayoutParams param1 =

                 new LinearLayout.LayoutParams(150, 65);

       param1.topMargin = 10;    param1.leftMargin = 10;

       layout.addView(ibtn1, param1);

       ibtn2 = new Button(this);        ibtn2.setOnClickListener(this);

       ibtn2.setText("Exit");             ibtn2.setBackgroundResource(R.drawable.mountain);

       layout.addView(ibtn2, param1);

       setContentView(layout);

       //-----------------------------------------------

       player = init();

   }

public void onClick(View v) {

       if(v == ibtn1) {

                 setTitle("playing...");

                 player.play(this);

            }

       else {

                 player.stop();

                 finish();

            }  

}

3.  結(jié)語

     由框架(的基類)來創(chuàng)建應(yīng)用(AP或App)子類的對象是框架開發(fā)的基本技巧。因為框架必需掌握重要對象的運行生命周期(Life-cycle)才能有效控制對象的行為,以及取重要的信息傳遞機制和內(nèi)容。如此,框架就能有效<框住>數(shù)以萬計的應(yīng)用程序,而不會失控了


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI