程序设计--也许每个新的Android项目建立时都该干的事。
虽然我的项目经验不是很丰富,但是,就接手过的几个项目来说,如果在项目建立时存在下面提到的那些东西将会给项目的进行带来很大的方便,编写以下的那些类是个很好的习惯,也许大家都会这么做的吧,通常我把它们放在总包的.app包内,如图:
看到这个图感觉熟悉的兄弟姐妹们就可以直接略过本篇啦...因为我要将要把它们一个个地拿出来长篇大论咯。
一、MyApplication(代表本项目的类,它继承自android.app.Application)
因为Application对象是在程序运行起来就创建在虚拟机中的,只有当程序退出之后它的对象才会销毁。所以它常用来创建和缓存程序中可能用到的对象的引用,这些对象往往是以单例存在的。下面的代码就创建和缓存了activityManager对象和excutor对象的引用。因为Application对象的常在特性也偶尔用来缓存一些小数据。如下面的字符串APPCONFIG。
1 /** 2 * 应用程序实体 3 * @author Change 4 * 5 */ 6 public class MyApplication extends Application { 7 private ActivityManager activityManager = null; // activity管理类 8 private Executor excutor = null; // 线程池执行器 9 public static String APPCONFIG = ""; // 程序中用来缓存应用程序配置字段 10 @Override 11 public void onCreate() { 12 activityManager = ActivityManager.getInstance(); // 获得实例 13 excutor = Executors.newFixedThreadPool(5); // 拥有固定数量5的线程池 14 super.onCreate(); 15 } 16 17 public ActivityManager getActivityManager(){ 18 return activityManager; 19 } 20 21 public Executor getExcutor() { 22 return excutor; 23 }
当然,这个类得在AndroidManifest.xml中配置以下才能使用。
只需要在<application>节点中添加如下代码即可。
android:name="您的项目包名.app.MyApplication"
那么,从现在起,我们就可以通过activity对象的getApplication()方法强制转换成MyApplication后的对象来使用它的方法了,如下我们用到了MyApplication中创建的线程池执行器。
1 ((MyApplication) getApplication()).getExcutor().execute(new Runnable() { 2 3 @Override 4 public void run() { 5 System.out.println("执行"); 6 } 7 });
下面我们还会在BaseActivity中使用它来获取activityManager。
二、ActivityManager(该类用来管理程序中所有的activity实例,如返回时只需要调用endActivity()结束当前activity,退出程序时调用finishAllActivity()结束所有activity,此外还有跳转到指定activity的方法:finishAllActivityExceptOne,这些在页面跳转时都是很方便的)
这种设计来源于面向对象的类比,activity就相当于一叠扑克牌,我们只能看到最上面的一张,而且越后放上的就先展示,那么用栈来管理最恰当不过了。
1 /** 2 * activity管理类,防止activity跳转混乱 3 * 4 * @author Change 5 */ 6 public class ActivityManager { 7 /** 8 * 接收activity的Stack 9 */ 10 private static Stack<Activity> activityStack = null; 11 private static ActivityManager activityManager = new ActivityManager(); 12 13 private ActivityManager(){} 14 15 /** 16 * 单实例 17 * 18 * @return 19 */ 20 public static ActivityManager getInstance() { 21 return activityManager; 22 } 23 24 25 /** 26 * 将activity移出栈 27 * 28 * @param activity 29 */ 30 public void popActivity(Activity activity) { 31 if (activity != null) { 32 activityStack.remove(activity); 33 } 34 } 35 36 /** 37 * 结束指定activity 38 * 39 * @param activity 40 */ 41 public void endActivity(Activity activity) { 42 if (activity != null) { 43 activity.finish(); 44 activityStack.remove(activity); 45 activity = null; 46 } 47 } 48 49 /** 50 * 获得当前的activity(即最上层) 51 * 52 * @return 53 */ 54 public Activity currentActivity() { 55 Activity activity = null; 56 if (!activityStack.empty()) 57 activity = activityStack.lastElement(); 58 return activity; 59 } 60 61 /** 62 * 将activity推入栈内 63 * 64 * @param activity 65 */ 66 public void pushActivity(Activity activity) { 67 if (activityStack == null) { 68 activityStack = new Stack<Activity>(); 69 } 70 activityStack.add(activity); 71 } 72 73 /** 74 * 弹出除cls外的所有activity 75 * 76 * @param cls 77 */ 78 public void popAllActivityExceptOne(Class<? extends Activity> cls) { 79 while (true) { 80 Activity activity = currentActivity(); 81 if (activity == null) { 82 break; 83 } 84 if (activity.getClass().equals(cls)) { 85 break; 86 } 87 popActivity(activity); 88 } 89 } 90 91 /** 92 * 结束除cls之外的所有activity,执行结果都会清空Stack 93 * 94 * @param cls 95 */ 96 public void finishAllActivityExceptOne(Class<? extends Activity> cls) { 97 while (!activityStack.empty()) { 98 Activity activity = currentActivity(); 99 if (activity.getClass().equals(cls)) { 100 popActivity(activity); 101 } else { 102 endActivity(activity); 103 } 104 } 105 } 106 107 /** 108 * 结束所有activity 109 */ 110 public void finishAllActivity() { 111 while (!activityStack.empty()) { 112 Activity activity = currentActivity(); 113 endActivity(activity); 114 } 115 } 116 }
如何使用更为恰当呢?接下来,我们看看BaseActivity这个类,上面两个类的基本使用均有体现。
三、BaseActivity(所有项目中定义的activity的父类,一般来所它继承Activity,如果程序中需要用到fragment,请继承FragmentActivity)
它的设计用到了继承,有高耦合的特性,以至于所有子类都能直接访问其中公用和受保护的方法。在其中执行了activity入栈操作,简化了子类activity的处理。并且在销毁activity让栈中的对应对象引用弹出。维护stack内数据的真确性。
1 /** 2 * activity基础类,作为程序中所有activity的父类,便于管理,与公有方法的调用。 3 * 4 * @author Change 5 * 6 */ 7 public class BaseActivity extends Activity { 8 @Override 9 protected void onCreate(Bundle b) { 10 requestWindowFeature(Window.FEATURE_NO_TITLE); 11 ((MyApplication) this.getApplication()).getActivityManager() 12 .pushActivity(this); // 将activity推入管理栈 13 super.onCreate(b); 14 } 15 16 @Override 17 protected void onDestroy() { // 销毁时activity出栈 18 ((MyApplication) this.getApplication()).getActivityManager() 19 .popActivity(this); 20 super.onDestroy(); 21 } 22 23 /** 24 * activity跳转 25 * @param from 26 * @param to 27 * @param data 携带数据 28 */ 29 protected void goTo(Context from,Class<? extends BaseActivity> to,Bundle data){ 30 Intent i = new Intent(); 31 i.setClass(from, to); 32 i.putExtras(data); 33 from.startActivity(i); 34 } 35 36 }
其中在
((MyApplication) this.getApplication()).getActivityManager() .pushActivity(this); // 将activity推入管理栈
用到了MyApplication对象中缓存的activityManager引用。
写代码是枯燥的,但设计却是有趣的,多思考,多观察,也许会有不同的收获,自勉,共勉。