Android SDK开发 — TitleBar重构 – 使用策略模式、舍弃代理模式
最后更新于:2022-04-01 10:06:08
代理模式
之前的使用如下。Activity和Fragment同时implement AppTitle
~~~
public abstract class BaseActivity extends Activity implements Handler.Callback, AppTitle {
~~~
~~~
public class BaseFragment extends Fragment implements AppTitle
~~~
修改后的
~~~
public class BaseFragment extends Fragment {
private AppTitle appTitle;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.d("fragment:onCreateView", getView());
//
appTitle = new TitleMgr(getActivity(), getView());
appTitle.initTitle();
}
public AppTitle getAppTitle() {
return appTitle;
}
public void setAppTitle(AppTitle appTitle) {
this.appTitle = appTitle;
}
~~~
采用策略模式
如果某个BaseFragment的样式不太一样,可以重新AppTitle模块。同时又不影响整体app的使用。
默认的实现类是TitleMgr
android SDK核心功能 — 消息传递与界面刷新
最后更新于:2022-04-01 10:06:05
今天来分享一下 项目中view刷新相关的核心功能。
android里线程之间消息的传递都是借助Handler来实现的
用到的场景主要是是Activity、Fragment、Application 、Service、Thread之间的消息互相传递
此实现必须借助抽象类来实现即
BaseActivity BaseFragment PhoebeApp (现在不讨论Service之间的消息传递)
先来看一下BaseActivity的实现
~~~
public abstract class BaseActivity extends Activity implements Handler.Callback{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMgr.push(this);
findViewById();
}
@Override
public boolean handleMessage(Message msg) {
return false;
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityMgr.remove(this);
}
}
~~~
其中BaseFragment的实现类似。省略
接下来看一下核心类
~~~
/**
* app中用于UI/非UI线程通信的核心工具类<br>
* 可以再"UI/非UI线程"往"UI线程"中发信息, 最终接收方为 {@link BaseActivity} {@link BaseFragment} {@link PhoebeApp}
*
* @author coffee<br>
* 2015-12-26下午4:36:26
*/
public class HandlerMgr {
public static void sendMessage(int what) {
int delayMillis = 0;
final Message msg = Message.obtain();
msg.what = what;
sendMessage(msg, delayMillis);
}
/**
* 将消息发往Application、Activity、Fragment
*
* @param orig
* @param delayMillis
*/
public static void sendMessage(Message orig, int delayMillis) {
// 发往application
Message appMessage = Message.obtain(orig);
PhoebeApp.getHandler().sendMessage(appMessage);
// 发往Activity
ArrayList<?> activities = ActivityMgr.getAllActivities();
for (final Object activity : activities) {
boolean result = handle(activity, orig, delayMillis);
if (result == true) {
break;// 停止继续分发该Message
} else {
continue;
}
}
// 发往Fragment
// ArrayList<?> fragments = FragmentMgr.getAllFragments();
// for (final Object fragment : fragments) {
// boolean result = handle(fragment, orig, delayMillis);
// if (result == true) {
// break;// 停止继续分发该Message
// } else {
// continue;
// }
// }
}
<span style="white-space:pre"> </span>
private static boolean handle(final Object activityOrFragment, Message orig, int delayMillis) {
final Message msg = Message.obtain(orig);
if (delayMillis == 0) {
boolean result = false;
if (activityOrFragment instanceof Handler.Callback) {
((Handler.Callback) activityOrFragment).handleMessage(msg);
}
return result;
} else {
PhoebeApp.getHandler().postDelayed(new Runnable() {
@Override
public void run() {
if (activityOrFragment instanceof Handler.Callback) {
((Handler.Callback) activityOrFragment).handleMessage(msg);
}
}
}, delayMillis);
}
return false;
}
}
~~~
如果Thread发送的http请求 。请求完成以后
~~~
public void run(){
// ...处理网络请求
Message msg = Message.obtain();
msg.what = 123;
msg.obj = "{json字符串}";
HandlerMgr.sendMessage(msg, 0);
}
~~~
这个时候如果你Activity需要接收返回的结果
~~~
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case 123:
String json = msg.obj + "";
//处理json数据
break;
}
}
~~~
如果你想在多个Activity处理该http返回的结果。只需要在Activity的handleMessage中加一个case就行了
如果需要在多个Activity中接收,这里需要注意一下handlerMessage的返回值
如果返回true 只会有一个Activity 接收到。剩下的都接收不到了。
~~~
for (final Object activity : activities) {
boolean result = handle(activity, orig, delayMillis);
if (result == true) {
break;// 停止继续分发该Message
} else {
continue;
}
}
~~~
Android SDK开发 — TitleBar重构 (代理模式-优化)
最后更新于:2022-04-01 10:06:03
上一篇讲到
[](http://blog.csdn.net/id19870510/article/details/50397129)[Android SDK开发 -- TitleBar重构 (代理模式的使用](http://blog.csdn.net/id19870510/article/details/50397129)[)](http://blog.csdn.net/id19870510/article/details/50397129)
然后补了一下代理设计模式。参考书籍《大话设计模式》
改善一下之前的代码设计。
先来定义一个接口
~~~
/**
* AppTitle接口
*
* @author coffee <br>
* 2016-1-2 下午10:17:53
*/
public interface AppTitle {
/**
* 初始化Title view
*/
public void initTitle();
/**
* 设置app的title
*
* @param leftTitle
* @param middleTitle
* @param rightTitle
*/
public void setTitle(TitleRes leftTitle, TitleRes middleTitle, TitleRes rightTitle);
}
~~~
接口的实现
~~~
public class TitleMgr implements AppTitle {
~~~
TitleMgr的实现参考上一篇文章
然后改善一下BaseActivity的类(该类相当于AppTitle的代理类,TitleMgr是AppTitle的实现类)
~~~
public abstract class BaseActivity extends Activity implements Handler.Callback, AppTitle {
private AppTitle appTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
<span style="white-space:pre"> </span>//....
findViewById();
}
/**
* 初始化title View
*/
protected void findViewById() {
initTitle();
}
@Override
public void initTitle() {
appTitle = new TitleMgr(getContext(), findViewById(android.R.id.content));
appTitle.initTitle();
}
/**
* 设置app的title栏
*
* @param leftTitle
* @param middleTitle
* @param rightTitle
*/
@Override
public void setTitle(TitleRes leftTitle, TitleRes middleTitle, TitleRes rightTitle) {
appTitle.setTitle(leftTitle, middleTitle, rightTitle);
}
~~~
BaseFragment的实现省略。。与Activity类似
至于为什么要定义一个接口AppTitle,而不是直接拿实现类TitleMgr来用。。
目前表示不是很理解。 网上所有的示例都采用接口来实现。。。。。。大概是为了统一代理类和实现类的操作吧。。
Android SDK开发 — TitleBar重构 (代理模式的使用)
最后更新于:2022-04-01 10:06:01
BaseFragment的TitleBar封装如下
~~~
public class BaseFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d("fragment:onCreateView", getView());
return null;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.d("fragment:onCreateView", getView());
findViewById();
}
private ViewSwitcher[] titleSwitcher;
/**
* 初始化View
*/
protected void findViewById() {
titleSwitcher = new ViewSwitcher[3];
titleSwitcher[0] = (ViewSwitcher) findViewById(R.id.app_title_left_switcher);
titleSwitcher[1] = (ViewSwitcher) findViewById(R.id.app_title_middle_switcher);
titleSwitcher[2] = (ViewSwitcher) findViewById(R.id.app_title_right_switcher);
}
protected void setTitle(TitleRes leftTitle, TitleRes middleTitle, TitleRes rightTitle) {
TitleRes[] reses = new TitleRes[] { leftTitle, middleTitle, rightTitle };
for (int i = 0; i < reses.length; i++) {
TitleRes res = reses[i];
ViewSwitcher switcher = titleSwitcher[i];
if (res == null) {
switcher.setVisibility(View.INVISIBLE);
} else {
switcher.setVisibility(View.VISIBLE);
// 触发单击事件的View
View clickView = null;
// 文字
if (res.getType() == 0) {
switcher.setDisplayedChild(0);// 显示TextView
//
Object resource = res.getResource();
String title = resource instanceof Integer ? getResources().getString((Integer) resource) : String.valueOf(resource);
((TextView) switcher.getChildAt(0)).setText(title);
clickView = switcher.getChildAt(0);
} else {
switcher.setDisplayedChild(1);// 显示ImageView
//
int imageResource = (Integer) res.getResource();
((ImageView) switcher.getChildAt(1)).setImageResource(imageResource);
clickView = switcher.getChildAt(1);
}
// 设置title的单击事件
clickView.setOnClickListener(res.getClickListener());
}
}
}
protected View findViewById(int id) {
return getView().findViewById(id);
}
}
~~~
子类调用
~~~
public class HomeFragment extends BaseFragment implements View.OnClickListener {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.home, container, false);
super.onCreateView(inflater, container, savedInstanceState);
return layout;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
findViewById(R.id.home_title_sample).setOnClickListener(this);
TitleRes left = null;
TitleRes middle = new TitleRes("首页标题");
TitleRes right = null;
setTitle(left, middle, right);
}
~~~
可以发现跟BaseActivity 中的代码实现基本上是类似的
但是BaseActivity和BaseFragment又没有共同的父类
这个时候需要采用 组合的方式进行代码重构
~~~
/**
* 因为Fragment和Activity没有共同的父类 ,但是他们各自的父类里又有一些TitleBar相同的业务逻辑处理<br>
* 所以我创建了该类
*
* @author coffee <br>
* 2015-12-24 下午10:26:10
*/
public class TitleMgr {
/**
* TitleBar的上下文
*/
private Context context;
/**
* TitleBar所在的顶层View容易
*/
private View contentView;
/**
* 三个Title
*/
private ViewSwitcher[] titleSwitcher;
public TitleMgr(Context context, View contenView) {
this.context = context;
this.contentView = contenView;
}
private Resources getResources() {
return context.getResources();
}
private View findViewById(int id) {
return contentView.findViewById(id);
}
/**
* 初始化title bar
*/
public void findViewById() {
titleSwitcher = new ViewSwitcher[3];
titleSwitcher[0] = (ViewSwitcher) findViewById(R.id.app_title_left_switcher);
titleSwitcher[1] = (ViewSwitcher) findViewById(R.id.app_title_middle_switcher);
titleSwitcher[2] = (ViewSwitcher) findViewById(R.id.app_title_right_switcher);
}
public void setTitle(TitleRes leftTitle, TitleRes middleTitle, TitleRes rightTitle) {
TitleRes[] reses = new TitleRes[] { leftTitle, middleTitle, rightTitle };
for (int i = 0; i < reses.length; i++) {
TitleRes res = reses[i];
ViewSwitcher switcher = titleSwitcher[i];
if (res == null) {
switcher.setVisibility(View.INVISIBLE);
} else {
switcher.setVisibility(View.VISIBLE);
// 触发单击事件的View
View clickView = null;
// 文字
if (res.getType() == 0) {
switcher.setDisplayedChild(0);// 显示TextView
//
Object resource = res.getResource();
String title = resource instanceof Integer ? getResources().getString((Integer) resource) : String.valueOf(resource);
((TextView) switcher.getChildAt(0)).setText(title);
clickView = switcher.getChildAt(0);
} else {
switcher.setDisplayedChild(1);// 显示ImageView
//
int imageResource = (Integer) res.getResource();
((ImageView) switcher.getChildAt(1)).setImageResource(imageResource);
clickView = switcher.getChildAt(1);
}
// 设置title的单击事件
clickView.setOnClickListener(res.getClickListener());
}
}
}
}
~~~
~~~
public class BaseFragment extends Fragment {
private TitleMgr titleMgr;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d("fragment:onCreateView", getView());
return null;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.d("fragment:onCreateView", getView());
//
titleMgr = new TitleMgr(getActivity(), getView());
titleMgr.findViewById();
}
protected void setTitle(TitleRes leftTitle, TitleRes middleTitle, TitleRes rightTitle) {
titleMgr.setTitle(leftTitle, middleTitle, rightTitle);
}
~~~
~~~
public abstract class BaseActivity extends Activity {
private TitleMgr titleMgr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMgr.push(this);
findViewById();
}
/**
* 初始化View
*/
protected void findViewById() {
titleMgr = new TitleMgr(getContext(), findViewById(android.R.id.content));
titleMgr.findViewById();
}
protected void setTitle(TitleRes leftTitle, TitleRes middleTitle, TitleRes rightTitle) {
titleMgr.setTitle(leftTitle, middleTitle, rightTitle);
}
~~~
我把业务逻辑抽出来放在单独写好的TitleMgr类中,然后BaseActivity和BaseFragment采用组合?也算是代理模式实现吧
android SDK开发 — TitleBar封装(二)
最后更新于:2022-04-01 10:05:59
android SDK开发 -- TitleBar封装 (一) [点击打开链接](http://blog.csdn.net/id19870510/article/details/50386067)
这一篇讲述一下TitleBar怎么增加交互
BaseActivity 中的逻辑实现
~~~
private ViewSwitcher[] titleSwitcher;
/**
* 初始化View
*/
protected void findViewById() {
titleSwitcher = new ViewSwitcher[3];
titleSwitcher[0] = (ViewSwitcher) findViewById(R.id.app_title_left_switcher);
titleSwitcher[1] = (ViewSwitcher) findViewById(R.id.app_title_middle_switcher);
titleSwitcher[2] = (ViewSwitcher) findViewById(R.id.app_title_right_switcher);
}
protected void setTitle(TitleRes leftTitle, TitleRes middleTitle, TitleRes rightTitle) {
TitleRes[] reses = new TitleRes[] { leftTitle, middleTitle, rightTitle };
for (int i = 0; i < reses.length; i++) {
TitleRes res = reses[i];
ViewSwitcher switcher = titleSwitcher[i];
if (res == null) {
switcher.setVisibility(View.INVISIBLE);
} else {
switcher.setVisibility(View.VISIBLE);
// 触发单击事件的View
View clickView = null;
// 文字
if (res.getType() == 0) {
switcher.setDisplayedChild(0);// 显示TextView
//
Object resource = res.getResource();
String title = resource instanceof Integer ? getResources().getString((Integer) resource) : String.valueOf(resource);
((TextView) switcher.getChildAt(0)).setText(title);
clickView = switcher.getChildAt(0);
} else {
switcher.setDisplayedChild(1);// 显示ImageView
//
int imageResource = (Integer) res.getResource();
((ImageView) switcher.getChildAt(1)).setImageResource(imageResource);
clickView = switcher.getChildAt(1);
}
// 设置title的单击事件
clickView.setOnClickListener(res.getClickListener());
}
}
}
~~~
自雷TitleSampleActivity 调用如下
~~~
@Override
protected void findViewById() {
setContentView(R.layout.title_demo);
super.findViewById();
// setTitle("返回主页", "这是一个Title", "下一个界面");
TitleRes left = new TitleRes("left", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(TitleDemoActivity.this, "click left", Toast.LENGTH_SHORT).show();
//showToast("click left");
}
});
TitleRes middle = new TitleRes("middle", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(TitleDemoActivity.this, "click middle", Toast.LENGTH_SHORT).show();
//showToast("click middle");
}
});
TitleRes right = new TitleRes("right", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(TitleDemoActivity.this, "click right", Toast.LENGTH_SHORT).show();
//showToast("click right");
}
});
//
setTitle(left, middle, right);
}
~~~
这个时候title三个控件都具备了交互的能力
Toast.makeText(TitleDemoActivity.this,"click right",Toast.* LENGTH_SHORT * ).show();
程序中会频繁的用到 context Toast等对象
采用Class.this的方式在代码移植、维护、重构等方面很不友好
另外频繁调用Toast每次都那么写的话 麻烦死
所以BaseActivity中新增俩方法
作用于暂且定义为protected 以后估计还得改
~~~
protected Context getContext() {
returnthis;
}
~~~
~~~
protectedvoid showToast(String message) {
Toast.*makeText*(getContext(), message,Toast.*LENGTH_SHORT*).show();
}
~~~
这个时候子类调用父类的代码如下
~~~
TitleRes left =newTitleRes("left",newView.OnClickListener() {
@Override
publicvoid onClick(View v) {
showToast("click left");//
}
});
。。。。中、右略
//
setTitle(left,middle, right);
~~~
android SDK开发 — TitleBar封装(一)
最后更新于:2022-04-01 10:05:56
假设app的title如下
假设app的title 统一的都是这种左中右结构的 代码如下
~~~
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/app_title_style"
android:baselineAligned="false"
android:gravity="center_vertical"
android:orientation="horizontal">
<ViewSwitcher
android:id="@+id/app_title_left_switcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/app_title_left_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回"/>
<ImageView
android:id="@+id/app_title_left_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</ViewSwitcher>
<ViewSwitcher
android:id="@+id/app_title_middle_switcher"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginLeft="16dip"
android:layout_weight="1">
<TextView
android:id="@+id/app_title_middle_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="title"/>
<ImageView
android:id="@+id/app_title_middle_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</ViewSwitcher>
<ViewSwitcher
android:id="@+id/app_title_right_switcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/app_title_right_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下一步"/>
<ImageView
android:id="@+id/app_title_right_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</ViewSwitcher>
</LinearLayout>
~~~
先来继续完善一下BaseActivity
~~~
protected void onCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
ActivityMgr.push(this);
findViewById();
}
// 初始化app中通用的控件
protected void findViewById(){
}
// 设置标题栏
protected void setTitle(){
}
~~~
然后看一下BaseActivity的具体实现类TitleDemoActivity
~~~
public class TitleDemoActivity extendsBaseActivity{
protectedvoid onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
protectedvoid findViewById(){
setContentView(R.layout.title_demo);
super.findViewById();
super.setTitle();// 设置标题栏
}
}
~~~
### TitleBar封装
BaseActivity的设计初衷是所有的Activity的都继承该类。
首先定义一些通用的属性、以及方法
~~~
private ViewSwitcher mLeftSwitcher;
private ViewSwitcher mMiddleSwitcher;
private ViewSwitcher mRightSwitcher;
/** * 初始化View */
protected void findViewById() {
mLeftSwitcher = (ViewSwitcher) findViewById(R.id.app_title_left_switcher);
mMiddleSwitcher = (ViewSwitcher) findViewById(R.id.app_title_middle_switcher);
mRightSwitcher = (ViewSwitcher) findViewById(R.id.app_title_right_switcher);
}
protected void setTitle(String left, String middle, String right) {
((TextView) mLeftSwitcher.getChildAt(0)).setText(left);
((TextView) mMiddleSwitcher.getChildAt(0)).setText(middle);
((TextView) mRightSwitcher.getChildAt(0)).setText(right);
}
~~~
子类调用
~~~
public class TitleDemoActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void findViewById() {
setContentView(R.layout.title_demo);
super.findViewById();
setTitle("返回主页", "这是一个Title", "下一个界面");
}
}
~~~
android SDK开发– 功能设计
最后更新于:2022-04-01 10:05:54
# 功能设计
先把app常用的功能进行抽象,主要从Activity Fragment Service等控件进行考虑。
其次完善相关的工具类。主要从代码封装、迭代、可维护性等方面考虑。
### 抽象
### Activity的抽象
Activity抽象主要目的是简化具体功能界面的工作量。主要通过代码封装的方式来达到效果。
同时需要处理网络请求、UI刷新等操作
### Fragment的抽象
Fragment的抽象与activity类似。但不同的是需要处理多个Fragment之间的互相调用,传参方式也不太一样。
### 工具类
App需要一个管理Activity或者Fragment的工具类,对其做全局的操作(方法调用) 为了减少代码的耦合度。不建议在Activity中直接加static引用。可以通过写一些工具类间接的实现。
Activity中访问网络请求以及回调刷新UI是一件比较繁琐的事儿。常规的做法是new一个Thread是传入一个Handler对象,网络请求完成以后sendMessage刷新。但是这种做法耦合度比较强,而且好多业务逻辑都需要在Activity中处理,代码臃肿
~~~
private Handler handler;
protected void onCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
handler= new handler(){
publicvoid handlerMessage(){
if(msg.what== 1){
//do sth
}
}
}
}
public class NetRunnable implementsRunnable{
privateHandler handler;
publicNetRunnable(Handler handler){
this.handler= handler;
}
publicvoid run(){
//do sth 处理网络等
Messagemsg = Message.obtain();
msg.what= 1;
msg.obj= “网络请求结果”;
this.handler.sendMessage(msg);
}
}
~~~
建议将网络请求的代码封装一下, 封装后续
### ActivityMgr
这个类的作用主要是保存app中所有正在运行的Activity的引用。
~~~
private static Stack<BaseActivity>activities = new Stack<BaseActivity >;
public static void push(BaseActivityactivity){
activities.push(activity);
}
public static void remove(BaseActivityactivity){
activities.remove(activity);
}
public class BaseActivity extends Activity
public void onCreate(BundlesaveInstanceState){
ActivityMgr.push(this);
}
public void onDestroy(){
ActivityMgr.remove(this);
}
~~~
解析一下为什么onDestroy的时候采用remove方法而不是pop()
防止acitivty AB, A启动 B 如果此时A#finish调用Stack#pop则会把B的引用移除
Fragment的工具类先略过
Android SDK开发 (三) App的属性配置
最后更新于:2022-04-01 10:05:52
# App的属性配置
一般app测试环境和线上环境好多配置都不同,比如说控制日志打印、服务器地址等
所以需要一个类专门进行app的属性配置。
至于为何不在PhoebeApp中写,一是减少PhoebeApp类的代码量,二分开写配置起来更自由。代码更清晰
因为是全局性的配置,所以类中的方法字段全部定义为static
~~~
package phoebe.frame;
import phoebe.frame.util.Log;
import android.app.Application;
/**
* 该类主要针对测试以及线上环境的不同而做一些属性配置操作
*
* @author coffee <br>
* 2015-12-17 下午8:48:18
*/
public class PhoebeConfig {
/**
* 默认开发环境 false表示线上正式环境
*/
private static boolean debug = true;
/**
* app接口服务器地址(线上环境)
*/
private static String serverUrl;
/**
* 同上 -- 测试环境
*/
private static String serverUrl_test;
/**
* 初始化进行app的配置 一般在 {@link Application#onCreate()}中配置
*/
public static void init() {
if (debug) {
Log.setOpen(true);
} else {
Log.setOpen(false);
}
}
/**
* 获取接口服务器的地址
*
* @return
*/
public static String getServerUrl() {
if (debug) {
return serverUrl_test;
} else {
return serverUrl;
}
}
}
~~~
定义完成以后 在PhoebeApp的onCreate中调用,使用
~~~
public class PhoebeApp extends Application {
<span style="white-space:pre"> </span>
@Override
public void onCreate() {
super.onCreate();
// 初始化app配置信息
PhoebeConfig.init();
}
~~~
做完以上工作,开始着手具体的功能设计。
Android sdk开发(二) Log日志类的设计
最后更新于:2022-04-01 10:05:50
# Log类的设计
正式代码设计之前我们先考虑一下日志类的使用。
日志主要用在调试app 一些复杂的业务流程,借助log 可以很容易找到问题所在
因为android.util.Log 定义为final类(不可继承) 所以我采用组合的方式才重写一个可以控制开关的日志工具类。考虑到Log应用的广泛性,所以定义为static,生命周期为全局
~~~
public class Log {
/**
* 日志的开关, false 表示不打印日志
*/
private static boolean open = false;
public static boolean isOpen() {
return open;
}
public static void setOpen(boolean open) {
Log.open = open;
}
~~~
Log的开关控制,一般在app初始化的地方设置。后续再讨论
~~~
public static void d(String tag, String msg){
if(open == false){
return; // 不打印日志
}
android.util.Log.d(tag,msg);
}
~~~
其中tag和msg 考虑到传入的参数需要频繁转型
比如说像打印一个int型的变量值。这时候会很不方便。同理其他非String类型的都需要转化为String 。
因为优化一下当前方法
~~~
public static voidd(Object tag, Object msg){
if(open == false){
return; // 不打印日志
}
android.util.Log.d(String.valueOf(tag), String.valueOf(msg));
}
~~~
这时候如果传入的 tag == null 或者“” 或者 包含有” ” \n\r等字符 ,那么输出的结果可能不是我们想要的,
接着继续优化一下该方法
~~~
package phoebe.frame.util;
/**
* 日志打印
*
* @author coffee <br>
*
* 2015-12-16 下午9:39:41
*/
public class Log {
/**
* 日志的开关, false 表示不打印日志
*/
private static boolean open = false;
public static boolean isOpen() {
return open;
}
public static void setOpen(boolean open) {
Log.open = open;
}
public static void d(Object tag, Object msg) {
if (open == false) {
return;
}
tag = handleMsgOrTag(tag);
msg = handleMsgOrTag(msg);
android.util.Log.d(String.valueOf(tag), String.valueOf(msg));
}
private static Object handleMsgOrTag(Object msgOrTag) {
if (msgOrTag == null) {
msgOrTag = "[null]";
} else if (msgOrTag.toString().trim().length() == 0) {
msgOrTag = "[\"\"]";
} else {
msgOrTag = msgOrTag.toString().trim();
}
return msgOrTag;
}
}
~~~
Android sdk开发(一)Application设计
最后更新于:2022-04-01 10:05:47
# Appllication的功能设计
每一个App都应该有一个扩展的Application。这个类中主要写一些整个app广泛用到的方法或app相关配置操作
application的生命周期是从app启动到退出。进程结束。所以在application中变量都定义为static, 也可以定义为非static。只是调用的时候稍微麻烦点
~~~
public classPhoebeApp extends android.app.Application
private static Context context;
private static Handler handler;
~~~
App的上下文引用,主要用于调用系统api
比如说 context.getSystemService(String name) 我们在app的方法中调用的时候可以
PhoebeApp.getContext().getSystemService(Context.NOTIFICATION_SREVICE)。 不需要每次使用的时候都传入参数Context,在类设计的时候可以更加自由。
另外App中会频繁用到handler与线程的交互。有时候我们需要用Handler#postDelayed(Runnable r , intdelayMills) 这个时候我们无需重新new handler(); 只需要调用全局的PhoebeApp#getHander() 即可
更高级的用法先不讲。后续再
至此一个基本的Application扩展类已经定义完成
~~~
package phoebe.frame;
import android.app.Application;
import android.content.Context;
import android.os.Handler;
/**
* 这个类中主要做一些全局的配置, 或者整个app广泛用到的方法逻辑<br>
*
* 生命周期从
*
* @author coffee<br>
* 2015-12-15下午3:28:30
*/
public class PhoebeApp extends Application {
/**
* app的上下文的引用,主要用于调用系统api的时候传参
*/
private static Context context;
/**
* 全局Handler 一般一个app只需要定义一个Handler就搞定了
*/
private static Handler handler;
@Override
public void onCreate() {
super.onCreate();
}
public static Context getContext() {
return context;
}
public static Handler getHandler() {
return handler;
}
}
~~~
Android sdk开发 – 序
最后更新于:2022-04-01 10:05:45
#序
文档是写给自己的。主要目的用来为公司后期的sdk迭代积累经验。相关技术点发布到网上没知会技术总监, 不知道会不会有啥后果。
欢迎对SDK开发感兴趣的朋友阅读。欢迎交流、分享经验。
阅读本文档需要一定的Java开发基础,面向对象的设计思想,以及Java反射、注解等高级应用。另外需要Android开发基础,如果还具备代码重构能力那就更好不过了。
工程源码位于[https://github.com/droidcoffee/Phoebe](https://github.com/droidcoffee/Phoebe)
[](https://github.com/droidcoffee/Phoebe)
目录
(一) Android SDK综合设计
[Application设计](http://blog.csdn.net/id19870510/article/details/50375912)
[Log设计](http://blog.csdn.net/id19870510/article/details/50375994)
[App的属性配置](http://blog.csdn.net/id19870510/article/details/50376016)
(二) Android SDK 功能设计
[Activity / Fragment的抽象](http://blog.csdn.net/id19870510/article/details/50376025) BaseActivity | BaseFragment
TitleBar的设计
一 [TiitleBar封装 ](http://blog.csdn.net/id19870510/article/details/50386067)
二 [TitleBar完善](http://blog.csdn.net/id19870510/article/details/50390460)
三 [TitleBar重构](http://blog.csdn.net/id19870510/article/details/50397129)
四 [TitleBar重构-优化(代理模式的使用)](http://blog.csdn.net/id19870510/article/details/50397129)
SDK核心功能
[消息的分发与界面的刷新](http://blog.csdn.net/id19870510/article/details/50482291)
前言
最后更新于:2022-04-01 10:05:43
> 原文出处:[android SDK开发](http://blog.csdn.net/column/details/phoebe.html)
作者:[id19870510](http://blog.csdn.net/id19870510)
**本系列文章经作者授权在看云整理发布,未经作者允许,请勿转载!**
# android SDK开发
> android sdk library 开发笔记