Android应用开发程序员,自己动手打造自己的专属应用框架转载请标明出处:http://http://blog.csdn.net/andr
Android应用开发程序员,自己动手打造自己的专属应用框架
UML类图中有些标记很容易混淆,这里先复习下,请大家看下面这幅图:

注:这幅图来自《大话设计模式》这本书中的插图。
二、应用框架:
A、基本概念
抽象(抽出共同之现象)——在同领域的程序中,常含有许多类别,这些类别有其共同点,我们将类别之共同结构抽离出来,称为抽象类别。其抽象之步骤是: 1、观察几个相似的类别;2、分辨它们的异同点;3、把它们的共同点抽离出来。
衍生(与众不同之现象)——基于通用结构里的抽象类别,添加些特殊功能(扩展),使之成为具体类别,再诞生对象。
所以抽象类别的存在目的,是要用其衍生子类别,而不是由它本身来诞生对象。由于抽象类别本身不诞生对象,所以有些方法并不完整。反之,类别之内的方法,皆是完整的,而且要用来诞生对象,就称它为具体类别。所谓不完整就是方法的方法体从缺,只有方法的描述。
B、打造自己的专属应用框架之类图:

上图中有关网络模块的请查看 Android仿人人客户端(v5.7.1)——网络模块处理的架构 这篇博文。
C、打造自己的专属应用框架之编码实现:
BaseApplication类源码如下:
package com.lbt.hairdesigner;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.view.Window;import android.widget.Toast;import com.lbt.hairdesigner.utils.LogUtil;/** * 功能描述:对Activity类进行扩展 * @author android_ls */public abstract class BaseActivity extends Activity { /** * LOG打印标签 */ private static final String TAG = BaseActivity.class.getSimpleName(); /** * 全局的Context {@link #mContext = this.getApplicationContext();} */ protected Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); int layoutId = getLayoutId(); if (layoutId != 0) { setContentView(layoutId); // 删除窗口背景 getWindow().setBackgroundDrawable(null); } mContext = this.getApplicationContext(); ((BaseApplication) this.getApplication()).addActivity(this); // 向用户展示信息前的准备工作在这个方法里处理 preliminary(); } /** * 向用户展示信息前的准备工作在这个方法里处理 */ protected void preliminary() { // 初始化组件 setupViews(); // 初始化数据 initialized(); } /** * 获取全局的Context * @return {@link #mContext = this.getApplicationContext();} */ public Context getContext() { return mContext; } /** * 布局文件ID * @return */ protected abstract int getLayoutId(); /** * 初始化组件 */ protected abstract void setupViews(); /** * 初始化数据 */ protected abstract void initialized(); /** * Debug输出Log信息 * @param tag * @param msg */ protected void debugLog(String msg) { LogUtil.d(TAG, msg); } /** * Error输出Log信息 * @param msg */ protected void errorLog(String msg) { LogUtil.e(TAG, msg); } /** * Info输出Log信息 * @param msg */ protected void showLog(String msg) { LogUtil.i(TAG, msg); } /** * 长时间显示Toast提示(来自String) * @param message */ protected void showToast(String message) { Toast.makeText(mContext, message, Toast.LENGTH_LONG).show(); } /** * 长时间显示Toast提示(来自res) * @param resId */ protected void showToast(int resId) { Toast.makeText(mContext, getString(resId), Toast.LENGTH_LONG).show(); } /** * 短暂显示Toast提示(来自res) * @param resId */ protected void showShortToast(int resId) { Toast.makeText(mContext, getString(resId), Toast.LENGTH_SHORT).show(); } /** * 短暂显示Toast提示(来自String) * @param text */ protected void showShortToast(String text) { Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show(); } /** * 通过Class跳转界面 **/ public void startActivity(Class<?> cls) { startActivity(cls, null); } /** * 含有Bundle通过Class跳转界面 **/ public void startActivity(Class<?> cls, Bundle bundle) { Intent intent = new Intent(); intent.setClass(this, cls); if (bundle != null) { intent.putExtras(bundle); } startActivity(intent); overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); } /** * 通过Action跳转界面 **/ public void startActivity(String action) { startActivity(action, null); } /** * 含有Bundle通过Action跳转界面 **/ public void startActivity(String action, Bundle bundle) { Intent intent = new Intent(); intent.setAction(action); if (bundle != null) { intent.putExtras(bundle); } startActivity(intent); overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); } /** * 含有Bundle通过Class打开编辑界面 **/ public void startActivityForResult(Class<?> cls, Bundle bundle, int requestCode) { Intent intent = new Intent(); intent.setClass(this, cls); if (bundle != null) { intent.putExtras(bundle); } startActivityForResult(intent, requestCode); overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); } /** * 带有右进右出动画的退出 */ @Override public void finish() { super.finish(); overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out); } /** * 默认退出 */ public void defaultFinish() { super.finish(); } }BaseNetworkActivity类源码如下:
package com.lbt.hairdesigner;import java.util.ArrayList;import java.util.List;import android.os.Bundle;import android.os.Handler;import com.lbt.hairdesigner.net.AsyncBaseRequest;import com.lbt.hairdesigner.net.DefaultThreadPool;/** * 功能描述:应用中需要访问网络的Activity基类 * @author android_ls */public abstract class BaseNetworkActivity extends BaseActivity { /** * 当前activity所持有的所有网络请求 */ protected List<AsyncBaseRequest> mAsyncRequests; /** * 当前activity所持有的Handler */ protected Handler mHandler; /** * 当前activity所持有的线程池对象 */ protected DefaultThreadPool mDefaultThreadPool; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } /** * 向用户展示信息前的准备工作在这个方法里处理 */ protected void preliminary() { mHandler = new Handler(); mAsyncRequests = new ArrayList<AsyncBaseRequest>(); mDefaultThreadPool = DefaultThreadPool.getInstance(); // 初始化组件 setupViews(); // 初始化数据 initialized(); } public List<AsyncBaseRequest> getAsyncRequests() { return mAsyncRequests; } public Handler getHandler() { return mHandler; } public DefaultThreadPool getDefaultThreadPool() { return mDefaultThreadPool; } @Override protected void onPause() { /** * 在activity暂停的时候,同时设置终止标识,终止异步线程 */ cancelAllRequest(); super.onPause(); } @Override protected void onDestroy() { /** * 在activity销毁的时候,同时设置终止标识,终止异步线程 */ cancelAllRequest(); super.onDestroy(); } /** * 取消当前Activity相关的网络请求 */ private void cancelAllRequest() { if (mAsyncRequests != null && mAsyncRequests.size() > 0) { try { int size = mAsyncRequests.size(); for (int i = 0; i < size; i++) { AsyncBaseRequest request = mAsyncRequests.get(i); request.setInterrupted(true); mAsyncRequests.remove(request); size = mAsyncRequests.size(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }PhotoNetworkActivity类源码如下:
2、具体实现层,个别类的源码
HairDesignerMainActivity类源码如下:
package com.lbt.hairdesigner.ph;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.util.TypedValue;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.RatingBar;import android.widget.RelativeLayout;import android.widget.TextView;import com.lbt.hairdesigner.BaseNetworkActivity;import com.lbt.hairdesigner.R;import com.lbt.hairdesigner.UGCFrameLayout;import com.lbt.hairdesigner.entity.CommentInfo;import com.lbt.hairdesigner.entity.PersonalHomeInfo;import com.lbt.hairdesigner.main.ClientHomepageActivity;import com.lbt.hairdesigner.main.MyCalendarActivity;import com.lbt.hairdesigner.personal.ChangePersonalInfoActivity;import com.lbt.hairdesigner.utils.BitmapUtil;import com.lbt.hairdesigner.utils.Constant;/** * 功能描述:我的主页 * @author android_ls */public class PersonalHomepageLayout extends UGCFrameLayout { /** * LOG打印标签 */ private static final String TAG = PersonalHomepageLayout.class.getSimpleName(); /**用户图像*/ private ImageView ivUserImage; private TextView tv_username; private ImageView iv_sex_icon; private RatingBar ratingbar; private TextView tv_price; private TextView tv_haoping; private TextView tv_yifuwu; private LinearLayout ll_yonghudianping_arrow; private TextView tv_dianping_count; private ImageView iv_dianping_user_icon; private TextView tv_dianping_nickname; private TextView tv_dianping_content; private TextView tv_dianping_time; private RelativeLayout rl_xijianchui; private RelativeLayout rl_tangfa; private RelativeLayout rl_ranfa; private RelativeLayout rl_huli; private TextView tv_xijianchui_price; private TextView tv_tangfa_price; private TextView tv_ranfa_price; private TextView tv_huli_price; private RelativeLayout rl_yuyue_shijian; private RelativeLayout rl_address; private RelativeLayout rl_haopinglv; private RelativeLayout rl_yifuwu; private TextView tv_address; private TextView tv_fujin_shangquan; private TextView tv_fujianxinxi; private LinearLayout ll_signature_arrow; private TextView tv_personalized_signature; private LinearLayout ll_happy_baby_show; private LinearLayout ll_happy_baby_show_arrow; private LinearLayout ll_coupon_list_arrow; private RelativeLayout rl_yonghu_dianping; private RelativeLayout rl_personal_jiamubiao; private RelativeLayout rl_signature; private RelativeLayout rl_happy_baby_show; private RelativeLayout rl_youhuixinxi; public PersonalHomepageLayout(BaseNetworkActivity activity) { super(activity); } @Override protected void setupViews() { super.setupViews(); topMenuNavbar.tvTitle.setText("我的主页"); tv_username = (TextView) viewRoot.findViewById(R.id.tv_username); ivUserImage = (ImageView) viewRoot.findViewById(R.id.iv_big_icon); iv_sex_icon = (ImageView) viewRoot.findViewById(R.id.iv_sex_icon); ratingbar = (RatingBar) viewRoot.findViewById(R.id.ratingbar); tv_price = (TextView) viewRoot.findViewById(R.id.tv_price); tv_haoping = (TextView) viewRoot.findViewById(R.id.tv_haoping); tv_yifuwu = (TextView) viewRoot.findViewById(R.id.tv_yifuwu); ll_yonghudianping_arrow = (LinearLayout) viewRoot.findViewById(R.id.ll_yonghudianping_arrow); ll_yonghudianping_arrow.setOnClickListener(this); tv_dianping_count = (TextView) viewRoot.findViewById(R.id.tv_dianping_count); iv_dianping_user_icon = (ImageView) viewRoot.findViewById(R.id.iv_dianping_user_icon); tv_dianping_nickname = (TextView) viewRoot.findViewById(R.id.tv_dianping_nickname); tv_dianping_content = (TextView) viewRoot.findViewById(R.id.tv_dianping_content); tv_dianping_time = (TextView) viewRoot.findViewById(R.id.tv_dianping_time); rl_xijianchui = (RelativeLayout) viewRoot.findViewById(R.id.rl_xijianchui); rl_tangfa = (RelativeLayout) viewRoot.findViewById(R.id.rl_tangfa); rl_ranfa = (RelativeLayout) viewRoot.findViewById(R.id.rl_ranfa); rl_huli = (RelativeLayout) viewRoot.findViewById(R.id.rl_huli); iv_dianping_user_icon.setOnClickListener(this); rl_xijianchui.setOnClickListener(this); rl_tangfa.setOnClickListener(this); rl_ranfa.setOnClickListener(this); rl_huli.setOnClickListener(this); rl_haopinglv = (RelativeLayout) viewRoot.findViewById(R.id.rl_haopinglv); rl_haopinglv.setOnClickListener(this); rl_yifuwu = (RelativeLayout) viewRoot.findViewById(R.id.rl_yifuwu); rl_yifuwu.setOnClickListener(this); tv_xijianchui_price = (TextView) viewRoot.findViewById(R.id.tv_xijianchui_price); tv_tangfa_price = (TextView) viewRoot.findViewById(R.id.tv_tangfa_price); tv_ranfa_price = (TextView) viewRoot.findViewById(R.id.tv_ranfa_price); tv_huli_price = (TextView) viewRoot.findViewById(R.id.tv_huli_price); rl_yuyue_shijian = (RelativeLayout) viewRoot.findViewById(R.id.rl_yuyue_shijian); rl_yuyue_shijian.setOnClickListener(this); rl_address = (RelativeLayout) viewRoot.findViewById(R.id.rl_address); rl_address.setOnClickListener(this); tv_address = (TextView) viewRoot.findViewById(R.id.tv_address); tv_fujin_shangquan = (TextView) viewRoot.findViewById(R.id.tv_fujin_shangquan); tv_fujianxinxi = (TextView) viewRoot.findViewById(R.id.tv_fujianxinxi); ll_signature_arrow = (LinearLayout) viewRoot.findViewById(R.id.ll_signature_arrow); ll_signature_arrow.setOnClickListener(this); tv_personalized_signature = (TextView) viewRoot.findViewById(R.id.tv_personalized_signature); ll_happy_baby_show = (LinearLayout) viewRoot.findViewById(R.id.ll_happy_baby_show); ll_happy_baby_show_arrow = (LinearLayout) viewRoot.findViewById(R.id.ll_happy_baby_show_arrow); ll_happy_baby_show_arrow.setOnClickListener(this); ll_coupon_list_arrow = (LinearLayout) viewRoot.findViewById(R.id.ll_coupon_list_arrow); ll_coupon_list_arrow.setOnClickListener(this); rl_yonghu_dianping = (RelativeLayout) viewRoot.findViewById(R.id.rl_yonghu_dianping); rl_yonghu_dianping.setOnClickListener(this); rl_personal_jiamubiao = (RelativeLayout) viewRoot.findViewById(R.id.rl_personal_jiamubiao); rl_personal_jiamubiao.setOnClickListener(this); rl_signature = (RelativeLayout) viewRoot.findViewById(R.id.rl_signature); rl_signature.setOnClickListener(this); rl_happy_baby_show = (RelativeLayout) viewRoot.findViewById(R.id.rl_happy_baby_show); rl_happy_baby_show.setOnClickListener(this); rl_youhuixinxi = (RelativeLayout) viewRoot.findViewById(R.id.rl_youhuixinxi); rl_youhuixinxi.setOnClickListener(this); } @Override public void onClick(View v) { Bundle bundle = new Bundle(); switch (v.getId()) { case R.id.rl_yonghu_dianping: case R.id.ll_yonghudianping_arrow: // 用户点评 mActivity.startActivity(UserCommentListActivity.class); break; case R.id.rl_personal_jiamubiao: case R.id.rl_xijianchui: mActivity.startActivity(PriceListActivity.class); break; case R.id.rl_tangfa: mActivity.startActivity(PriceListActivity.class); break; case R.id.rl_ranfa: mActivity.startActivity(PriceListActivity.class); break; case R.id.rl_huli: mActivity.startActivity(PriceListActivity.class); break; case R.id.rl_yuyue_shijian: bundle.putInt("flage", Constant.PERSONAL_HOMEPAGE_MY_CALENDAR_CODE); mActivity.startActivity(MyCalendarActivity.class, bundle); break; case R.id.rl_address: mActivity.startActivity(ShopListActivity.class); break; case R.id.ll_signature_arrow: case R.id.rl_signature: bundle.putInt("flage", Constant.CHANGE_PERSOANL_SIGNATURE_CODE); bundle.putString("signature", tv_personalized_signature.getText().toString()); mActivity.startActivity(ChangePersonalInfoActivity.class, bundle); break; case R.id.ll_happy_baby_show_arrow: case R.id.rl_happy_baby_show: mActivity.startActivity(WorksShowActivity.class); break; case R.id.rl_haopinglv: bundle.putInt("flage", Constant.REVIEW_HAOPINGLV_CODE); mActivity.startActivity(ReviewActivity.class, bundle); break; case R.id.rl_yifuwu: bundle.putInt("flage", Constant.REVIEW_YIFUWU_CODE); mActivity.startActivity(ReviewActivity.class, bundle); break; case R.id.ll_coupon_list_arrow: case R.id.rl_youhuixinxi: mActivity.startActivity(CouponListActivity.class); break; case R.id.iv_dianping_user_icon: // 点评用户的图像单击事件处理 mActivity.startActivity(ClientHomepageActivity.class); break; default: super.onClick(v); break; } } @Override protected int getLayoutId() { return R.layout.personal_homepage; } @Override protected void initialized() { // 构造测试数据 PersonalHomeInfo personalHome = new PersonalHomeInfo(); personalHome.setUid(1004); personalHome.setName("王念西"); // personalBaseInfo.setHeadurl(""); // personalBaseInfo.setTinyurl(""); personalHome.setMainurl(""); personalHome.setSex(1); personalHome.setStar(4f); personalHome.setPrice(200); personalHome.setGoodReputation(0.5); personalHome.setYifuwu(50); personalHome.setCommentCount(126); CommentInfo commentInfo = new CommentInfo(); commentInfo.setCid(102); commentInfo.setUid(23); commentInfo.setNickname("Vicy1985"); commentInfo.setIconPath(""); commentInfo.setContent("很时尚,不错,这个发型我喜欢,好评,下次还会找你剪头发。"); commentInfo.setTime("2013-05-03 09:38"); personalHome.setCommentInfo(commentInfo); // 用户基本信息字段赋值 tv_username.setText(personalHome.getName()); Bitmap bitmap = BitmapFactory.decodeResource(mActivity.getResources(), R.drawable.user_big_icon); ivUserImage.setImageBitmap(BitmapUtil.drawRoundBitmap(bitmap, 8)); if (personalHome.getSex() == 1) { iv_sex_icon.setImageResource(R.drawable.sex_man); } else { iv_sex_icon.setImageResource(R.drawable.jishi_female); } ratingbar.setRating(personalHome.getStar()); tv_price.setText("均价:" + (int) personalHome.getPrice() + "元"); tv_haoping.setText((int) (personalHome.getGoodReputation() * 100) + "%"); tv_yifuwu.setText(personalHome.getYifuwu() + ""); // 用户点评字段赋值 tv_dianping_count.setText("共" + personalHome.getCommentCount() + "条"); CommentInfo comment = personalHome.getCommentInfo(); tv_dianping_nickname.setText(comment.getNickname()); tv_dianping_content.setText(comment.getContent()); tv_dianping_time.setText(comment.getTime()); Bitmap bitmap1 = BitmapFactory.decodeResource(mActivity.getResources(), R.drawable.user_icon); iv_dianping_user_icon.setImageBitmap(BitmapUtil.drawRoundBitmap(bitmap1, 8)); // 价目表字段赋值 tv_xijianchui_price.setText("小于100"); tv_tangfa_price.setText("600-1000"); tv_ranfa_price.setText("600-1000"); tv_huli_price.setText("600-1000"); // 场地字段赋值 tv_address.setText("地址:上海市长宁区安顺路1026号"); tv_fujin_shangquan.setText("附近商圈:古北"); tv_fujianxinxi.setText("免费停车、免费无线上网"); // 个性签名字段赋值 tv_personalized_signature.setText("我一直在发行业五年,现在一个艺术家工作的可爱的无与伦比的头发工作室,位于旧金山的SOMA区..."); int[] images = { R.drawable.f1, R.drawable.f2, R.drawable.f3, R.drawable.f4, R.drawable.f5, R.drawable.f6, R.drawable.f7, R.drawable.f8,R.drawable.f9, R.drawable.f10, R.drawable.f13, R.drawable.f12, R.drawable.f14, R.drawable.f15, R.drawable.f16, R.drawable.f17, R.drawable.f18, R.drawable.f19 }; for (int i = 0; i < images.length; i++) { // 显示最近头像 ImageView imageView = new ImageView(mActivity); int widthAndHeight = pxTodip(60); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(widthAndHeight, widthAndHeight); params.rightMargin = pxTodip(10); imageView.setLayoutParams(params); // imageView.setPadding(0, pxTodip(5), 0, pxTodip(5)); // imageView.setBackgroundResource(R.drawable.select_friend_avatar_frame); Bitmap bitmap2 = BitmapFactory.decodeResource(mActivity.getResources(), images[i]); imageView.setImageBitmap(BitmapUtil.drawRoundBitmap(bitmap2, 8)); ll_happy_baby_show.addView(imageView); ll_happy_baby_show.invalidate(); imageView.setOnClickListener(new OnClickListener() { public void onClick(View v) { } }); } } private int pxTodip(float valuepx) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valuepx, mActivity.getResources().getDisplayMetrics()); }}
四、写在最后面的话:向大家推荐高焕堂的《Android应用框架原理与程序设计》这本书,相信你看后会获益良多。





