介绍
之前写过一篇 android应用开发MVC框架(一) ,里面也有简单介绍了mvc是什么,如果不了解的童鞋可以看一下。本文是另外一种实现方式,也是基于接口回调的思想实现的一种方式,我自己在开发中比较喜欢用这种方式开发,因为这种架构可以让项目结构变得比较清晰。还是老习惯,通过一个简单得不能再简单得demo来演示,我觉得我分享的是一种思想、一种方式,喜欢的可以看看,也可以在这个基础上继续改进,交流学习。不喜勿喷哦。有问题可以评论提出来,毕竟都是在学习中。以后还会继续研究应用框架的搭建的。
首先看一下项目结构图:
这里简单说明一下,一般应用开发都会按照模块分开,这里也是,本demo是模拟一个很简单得新闻获取功能(就一个模块),news包就是新闻模块,GetNewsBusiness.java 就是新闻模块的业务处理层,GetNewsController.java 是新闻模块的控制层,而数据展示就在ui包里面;model包是放实体类,也就是常说的bean;common里面放的是一些通用的。
下面通过代码对每个类做下解释:
CallBackInterface.java
回调接口,里面的方法在需要回调的地方实现此接口,然后将其作为参数传到有数据回调的地方去。这里是在业务层有数据回调,控制层实现回调接口拿到数据之后通过handler将数据传给activity。
package com.kroc.controller;
/**
* @author 林楷鹏
* @描述 回调函数接口
*/
public interface CallBackInterface {
/**
* 返回回调结果
* @param key 状态值
* @param param 可变参数
*/
public void displayResult(int key, Object...param);
}
News.java
新闻实体类
package com.kroc.model;
public class News {
private String title;
private String content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "News [title=" + title + ", content=" + content + "]";
}
}
GetNewsBusiness.java
这里是业务处理层,可以看到不同的构造函数可以实现不同参数的传入。然后核心是在getNews方法当中,这里是开启一个子线程执行耗时操作,以免阻塞主线程,在代码当中可以看到,方法传入了我们上面所定义的接口作为参数,这里可以将我们获取的结果回调回去,这里有一个好处很明显,就是回调当中,你可以根据访问结果的不同(成功或者失败或者超时等等),设置回调状态和回调数据,然后等下在activity作相应处理,详细见下面MainActivity.java
package com.kroc.news;
import android.content.ContentValues;
import com.kroc.common.Constants;
import com.kroc.controller.CallBackInterface;
import com.kroc.model.News;
/**
*
* @author 林楷鹏
* @描述: 获取新闻业务处理层
*
*/
public class GetNewsBusiness {
public GetNewsBusiness() {
}
public GetNewsBusiness(String url, ContentValues values) {
}
/**
* 联网获取新闻
* @param callBackInterface 回调接口
*/
public void getNews(final CallBackInterface callBackInterface) {
new Thread() {
public void run() {
try {
Thread.sleep(5 * 1000);//模拟5秒访问网络
News news = new News();
news.setTitle("这里是标题");
news.setContent("contentcontentcontentcontent");
//访问成功,将结果回调
callBackInterface.displayResult(Constants.SUCCESS, news);
} catch (InterruptedException e) {
//发生错误,回调异常信息
callBackInterface.displayResult(Constants.FAIL, "异常:"+e.getMessage());
}
}
}.start();
}
}
GetNewsController.java
这里 GetNewsController + activity 充当的是控制层,控制层的存在是可以进一步将构架的耦合性降低,起到一个桥梁作用,在这里将业务层得到的数据返回到activity当中去,如果写得规范,设计得合理一些的话,可以多个模块使用同一个控制层的。代码当中可以看到,我们在这里实现回调接口,并在接口中的方法里面接收数据,并将数据装进message当中发回到activity中。而这里再扩展一下,就是下面注释掉的那个map,实际应用当中,如果你的数据变化不会很大的话,可以根据实际情况引入缓存机制,增加效率,就不用每次都联网获取数据。
package com.kroc.news;
import android.content.ContentValues;
import android.os.Handler;
import android.os.Message;
import com.kroc.controller.CallBackInterface;
/**
*
* @author 林楷鹏
* @描述: 获取新闻控制层
*
*/
public class GetNewsController {
private GetNewsBusiness business;
private Handler handler;
// private HashMap<String, GetNewsBusiness> map;//这里可以加入缓存机制等等,按需求
public GetNewsController() {
business = new GetNewsBusiness();
}
public GetNewsController(String url, ContentValues values) {
business = new GetNewsBusiness(url, values);
}
/**
* 获取访问结果
* @param handler
*/
public void getResult(Handler handler){
this.handler = handler;
business.getNews(callBackInterface);
}
//实现回调接口
private CallBackInterface callBackInterface = new CallBackInterface() {
@Override
public void displayResult(int key, Object... param) {
Message msg = new Message();
msg.what = key;
msg.obj = param[0];//这里注意,要param[0],因为可变参数是个数组
handler.sendMessage(msg);
}
};
}
MainActivity.java
这里就是activity了,也属于 controller 层,可以将得到的数据交给 View 展示出来,在这里实现handler,然后在handler当中获取到数据,再将数据展示出来。
package com.kroc.ui;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.kroc.common.Constants;
import com.kroc.model.News;
import com.kroc.news.GetNewsController;
public class MainActivity extends Activity {
private Button get_news_btn;
private ProgressDialog progress;
private TextView show_txtv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView(){
get_news_btn = (Button)findViewById(R.id.get_news_btn);
get_news_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
progress = new ProgressDialog(MainActivity.this);
progress.setTitle("获取新闻");
progress.setMessage("正在加载...");
progress.show();
GetNewsController controller = new GetNewsController();
controller.getResult(handler);
}
});
show_txtv = (TextView)findViewById(R.id.news_txtv);
}
//处理结果、更新界面
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
progress.dismiss();
//在这个里面可以处理回调的结果
switch (msg.what) {
case Constants.SUCCESS:
News news = (News)msg.obj;
show_txtv.setText(news.toString());//显示结果
break;
case Constants.FAIL:
//处理失败结果
show_txtv.setText(msg.obj.toString());//如果错误,将错误信息显示
break;
}
};
};
}
View 就是各种 xml ,这里就不详细介绍。
好了,基本就是这样简单介绍。如果有兴趣或疑问的,可以留下评论。也可以下载代码看看。不好之处还望指出,哒哒。
最后再来两张简单得不能再简单得效果图,说明这个demo是跑得通的,哈哈。