“第二届 Google 暑期大学生博客分享大赛 - 2011 Android 成长篇 ”
去年得知博客分享大赛已经到了投票阶段,今年再三思考,想写点有价值的东西分享。
虽然一段时间由于各种原因没有发博客,但希望没有生疏吧。话不多说,这里我选择之前一个项目中用到的开源项目Droid-Fu作为这篇文章的话题。从第一次使用时只有官网博客上的简单信息,到现在网上也陆续有了对作者博客上介绍的使用方法的中文翻译和一点简单的介绍,但是明显在使用时候还是摸不到头绪,毕竟作者对具体使用方法介绍的比较少,api略显笼统,很难投入到应用中,我希望能通过对方法详细的介绍让大家了解、方便的利用Droid-Fu,并为这个开源项目作出贡献。
1. Droid-Fo初体验
显然,要了解它,首先应该说清楚它是什么,标题中提到了它是做什么的,但毕竟太笼统。首先我不得不先提到给我们开发者带来巨大方便的作者Jabber,就在这里把作者对这个项目的介绍作为一个入口吧:
通过这个地址你可以找到更多的资源和作者的介绍。关于这个项目,这里我尊重作者的介绍:
Droid-Fu contains utility classes as well as some self-contained, ready to use Android components, all of which I consider useful for typical Android applications. Some of the areas for which Droid-Fu offers
support classes include:
application life-cycle
background tasks
HTTP messaging
(remote) image handling
custom adapters
… and more. The library is still young, so expect to see a lot more stuff forthcoming!
由于浏览博客都可以得到问题的答案,我这里想详细提到的就是它能给大家带来什么方便。当然建议这之前您先了解它是做什么的。
从我的认识,作者为什么取名better+android提供的几大主体生命形式,是因为它很好的解决了异步问题,简单的说是后台任务的一个非常好选择。也许你用过android sdk中带有的AsyncTask,与之类似,主要将整个项目的所有异步问题予以处理。这是在项目用到的最主要的部分,如果您有什么看法和使用经验欢迎提出建议了!
2. Droid-Fo与AsyncTask
先说SDK中自带的AsyncTask,AsyncTask提供了一个很好的机制,例如在访问web服务器、后台处理数据时最经常使用到异步任务,AsyncTask使得我们能在出完数据后反馈到activity的方式来完成异步处理。但做多了移动项目大家都会首先考虑一个问题,就是软件运行时候的来电中断是否需要处理,而对于android中activity在来电进中断状态的机制,自然关于界面的操作都必须要考虑这个问题。而AsyncTask无法很好的解决这个问题,并且通过测试在中断activity的操作中都会使得AsyncTask表现出不稳定,所以才有了Droid-Fo解决这些问题。虽然可以通过定时查看和重复发送机制解决这些问题,但是代价是我们不希望看到的。Droid-Fo是在原有的一些类基础上修改过后的产品,所以这个开源项目并不神秘,大量的引用了android自带的SDK。说到这里应该不必再介绍Droid-Fo的优点了。
3. Droid-Fo基本格式
我们来做一个demo,主要完成以下功能:
一个含有textview的界面,在程序被加载时就执行后台任务。
后台任务返回1,而整个task返回0和后台任务的返回值到界面的textview显示。
后台任务和接受到后台返回参数时需要打印debug属性的日志
首先介绍下使用Droid-Fo的基本格式:
[1]. 需要在根目录生成一个继承自DroidFuApplication的类,如本例使用MyApplication类作为此继承类,不需要写入内容
[2]. 在AndroidManifest.xml需要定义application的android:name标签修改为此类,本例定义如下
<application android:name=".MyApplication" android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".InterfaceTest" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
[3]. 继承自BetterDefaultActivity的Activity,本例只有入口Activity为InterfaceTest
[4]. 再加上继承自BetterAsyncTask的一个task类
[5]. string.xml中如下定义
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, InterfaceTest!</string> <string name="app_name">InterfaceTest</string> <string name="droidfu_progress_dialog_title">droidfu_progress_dialog_title</string> <string name="droidfu_progress_dialog_message">正在进行</string> </resources>
可以看到第3、4个为与不同string.xml的区别,如果缺少将不能正常运行。简单说下,第3个是如果需要等待时,显示的等待dialog的标题,第四个自然是dialog的内容
也许您在读作者的介绍时没有找到这些缺一不可的元素,那么我的第一个小目的算是达到了,起码能帮助你成功的完成最简单的一个Droid-Fo应用,完成后台任务。解决了作者说明不清、缺少文档的小小缺陷。
4. 项目中的Droid-Fo(demo)
代码不多,我们直接一个个来看
(以下是我在项目中使用的框架形式,主要是将activity继承特定接口,使得很多相似的功能可以抽象为共同的接口来处理,比如同样为添加操作,可以在界面端提示相同的内容;或者指定申请的类型,来判断反馈信息的内容,这时申请格式又可能可以统一来处理,如同样添加梨子和苹果和传入pearTaskId和appleTaskId来区分反馈信息的处理。从而实现了页面与底层逻辑的分离,将界面处理放在activity中,而后台操作放在task中去做)
AddMethod.java(提供接口方法,用来在界面端响应反馈信息)
package org.dreamfly.interfacetest;
public interface AddMethod {
public abstract void addResultHandler(int i1,Object i2);
}
package org.dreamfly.interfacetest;
import android.content.Context;
import android.util.Log;
import com.github.droidfu.concurrent.BetterAsyncTask;
public class NewAsyncTask extends
BetterAsyncTask<String, Void, String> {
AddMethod addMethod;
/**
* Constructor
* @param arg0
* @param addMethod :the interface,it is also the Activity arg0
* @param needDialog :need dialog or not when the task run in background for holding
*/
public NewAsyncTask(Context arg0,AddMethod addMethod ,Boolean needDialog) {
super(arg0);
// TODO Auto-generated constructor stub
this.addMethod=addMethod;
if(!needDialog){
super.disableDialog();
}
}
/**
* when the handling of asynctask end, system call the after() method
*/
@Override
protected void after(Context arg0, String obj) {
// TODO Auto-generated method stub
final Object obj2=obj;
Log.d(Constants.logTag, "the obj receive by method after:"+obj+".");
addMethod.addResultHandler(0, obj2);
}
@Override
protected void handleError(Context arg0, Exception arg1) {
// TODO Auto-generated method stub
}
/**
* asynctask , do in backgroud
*/
protected String doCheckedInBackground(Context context,String... obj) throws Exception{
super.doCheckedInBackground(context, obj);
Log.d(Constants.logTag, "this is docheckedinbackground, i'll return 1.");
return 1+"";
}
}
package org.dreamfly.interfacetest;
import com.github.droidfu.activities.BetterDefaultActivity;
import android.os.Bundle;
import android.widget.TextView;
public class InterfaceTest extends BetterDefaultActivity implements AddMethod{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
NewAsyncTask na=new NewAsyncTask(this,this,true);
na.execute();
}
/**
* handle the async result
*/
public void addResultHandler(int i1, Object i2) {
// TODO Auto-generated method stub
TextView tv=(TextView)findViewById(R.id.text);
tv.setText(i1+" "+i2);
}
}
好了,这里应该可以清楚的看出这个框架的格式了。功能很简单,想通过最简单的形式来表现固定的格式。在真实中小型项目开发中效率和运行结果都很可观。
5. demo的运行结果
像前面所说的demo实现的功能很简单,这里我们为了能更好的了解流程,贴出需求中提出的运行结果和log信息:
最后附件中附上工程和源码,希望大家能快捷的上手这个还发展不完全的开源项目,解决您遇到的异步信息处理问题。好的开源项目需要大家一起去推动,希望共同努力的同时我们都可以为Droid-Fu作出一份贡献,让它方便更多的开发者。