有关MVP模式的介绍,这里不作详细解释,稍后会更新MVP设计模式,请等待链接……
通过mvp设计模式,(MVP的主要优势是将view层和model层完全解偶)解析json数据,然后展示到ListView上,所有的讲解将通过注释详细解释
MainActivity.java
public class MainActivity extends AppCompatActivity implements ViewInter {
//需要显示的数据项
private ListView mList;
//自定义的适配器
private MyAdapter adapter;
//对应json数据的地址
private String path= "http://api102.meishi.cc/v5/class_list1.php?lon=&source=android&cid=6&vk=2417a0052eac5cd81d5dce4d168a3973&sort_sc=asc&sort=default&lat=&page=%d&bcid=13&format=json";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取ListView的id
mList = (ListView)findViewById(R.id.mList);
//view层告诉presenter层,我需要数据,然后对应的presenter就相当于一个传递者,找模型层去拿对
//应的数据
new Presenter(this).load(String.format(path,2));
}
/**
* 通过结果回调的方式,拿到对应的数据
* @param dataBeen ListView上所显示的数据项
*/
@Override
public void showData(List dataBeen) {
//创建自定义适配器
adapter = new MyAdapter(dataBeen);
//设置适配器
mList.setAdapter(adapter);
}
}
ViewInter.java
public interface ViewInter {
/**
* 定义一个通用功能的接口,所有需要更新界面的功能都放这这里面
* @param dataBeen
*/
void showData(List dataBeen);
}
Presenter.java
public class Presenter {
//模型层数据类型
ModelInter modelInter;
//视图层数据类型
ViewInter viewInter;
//这里只需要获得view层的数据类型即可
public Presenter(ViewInter viewInter){
this.viewInter = viewInter;
//同时创建模型层,主要是为了拿对应的数据
modelInter = new ModelImp();
}
/**
* 视图层需要数据时,只需要调用次方法就可以拿到对应的数据
* @param path 对应的json数据地址
*/
public void load(String path){
/**
* 通过模型层的getData方法拿对应的数据
* 通过匿名内部类实现ModelInter.OnDataCompleteListener
* 接口中的onLoadComplete方法,主要功能是解析
* json数据到实体中,这里是用的Google的Gson解析Json
*/
modelInter.getData(new ModelInter.OnDataCompleteListener() {
@Override
public void onLoadComplete(byte[] bytes, String path) {
//通过接口回调传过来的bytes转化为字符串
String json = new String(bytes);
//解析到对应的实体类
HotFoodBean foodBean = new Gson().fromJson(json, HotFoodBean.class);
//将数据返回给view层
viewInter.showData(foodBean.getObj().getData());
}
},path);
}
}
ModelInter.java
//模型层中的所有功能,都写在这个接口中
public interface ModelInter {
/**
* 这个方法是通过网络获取Json数据
* @param listener 网络数据回调的实例
* @param path Json数据的网络地址
*/
void getData(OnDataCompleteListener listener,String path);
//网络请求完成后的接口回调方法,实现这个接口可以获取Json数据
public interface OnDataCompleteListener{
void onLoadComplete(byte[] bytes,String path);
}
}
ModelImp.java
public class ModelImp implements ModelInter{
/**
* 调用异步任务获取Json数据
* @param listener 网络数据回调的实例
* @param path Json数据的网络地址
*/
@Override
public void getData(OnDataCompleteListener listener,String path) {
new MyAsyncTask(listener).execute(path);
}
}
MyAsyncTask.java
public class MyAsyncTask extends AsyncTask<String, Void, byte[]> {
//Json数据的地址
private String path;
//接口回调的实例
private ModelInter.OnDataCompleteListener listener;
public MyAsyncTask(ModelInter.OnDataCompleteListener listener) {
this.listener = listener;
}
/**
* 异步任务方法,在子线程中执行
* @param params 访问网络的地址
* @return 返回请求到的数据,然后执行onPostExecute方法
*/
@Override
protected byte[] doInBackground(String... params) {
//将当前地址保存起来
path = params[0];
return getURLData(path);
}
/**
* 获取返回的数据之后执行相应的操作
* @param bytes 传过来的数据
*/
@Override
protected void onPostExecute(byte[] bytes) {
super.onPostExecute(bytes);
//如果返回来的数据不为空,并且接口实例不为空,实现接口回调
if (listener != null && bytes != null) {
listener.onLoadComplete(bytes,path);
}
}
/**
* 网络请求功能
* @param path 网络请求地址
* @return 返回数据
*/
private byte[] getURLData(String path) {
try {
//建立URL请求
URL url = new URL(path);
//转换成HttpURLConnection
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//请求方式为GET
connection.setRequestMethod("GET");
//读取超时时间为5秒
connection.setReadTimeout(5000);
//连接超时实际为5秒
connection.setConnectTimeout(5000);
//开始连接,相当于在地址栏输入网址后敲回车键
connection.connect();
//返回200代码表示访问成功
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
//获取服务器返回的字节流
BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
//将数据保存到内存流中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = -1;
byte[] bytes = new byte[1024 * 8];
while (-1 != (len = bis.read(bytes))) {
baos.write(bytes, 0, len);
}
bis.close();
return baos.toByteArray();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
MyBaseAdapter.java
/**
* 主要是抽取通用的三个方法
*/
public abstract class MyBaseAdapter extends BaseAdapter{
private List foodBeen;
public MyBaseAdapter(List foodBeen){
this.foodBeen = foodBeen;
}
@Override
public int getCount() {
return foodBeen == null ? 0:foodBeen.size();
}
@Override
public Object getItem(int position) {
return foodBeen.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public List getFoodBeen() {
return foodBeen;
}
}
MyAdapter.java
public class MyAdapter extends MyBaseAdapter {
//将数据传递给父类
public MyAdapter(List foodBeen) {
super(foodBeen);
}
/**
* 解析布局,将每个布局返回,展示到界面上
*
* @param position 位置
* @param convertView 可复用的控件,滑出屏幕后就会变成可复用
* @param parent 表示ListView控件
* @return 返回布局
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//每次先获取将要展示的数据
HotFoodBean.ObjBean.DataBean dataBean = getFoodBeen().get(position);
//优化布局的帮助类
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
//查找对应控件,并设置到帮助类中,以免重复创建,是内存泄露,
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.mImg);
//以下四个控件同上
viewHolder.rat = (RatingBar) convertView.findViewById(R.id.mRat);
viewHolder.title = (TextView) convertView.findViewById(R.id.mTitle);
viewHolder.step = (TextView) convertView.findViewById(R.id.mStep);
viewHolder.taste = (TextView) convertView.findViewById(R.id.mTaste);
//将viewHolder类保存到每个对象的标记中,方便下次获取
convertView.setTag(viewHolder);
}
//以下控件设置对应的数据
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.title.setText(dataBean.getTitle());
viewHolder.rat.setRating(Float.parseFloat(dataBean.getRate()));
viewHolder.step.setText(dataBean.getStep() + "/" + dataBean.getMt());
viewHolder.taste.setText(dataBean.getKouwei() + "/" + dataBean.getGongyi());
//这里的作用是,为了防止已经下载显示了的图片重复请求,如有不懂,欢迎提问
viewHolder.imageView.setTag(dataBean.getTitlepic());
//每次将图片都置空
viewHolder.imageView.setImageBitmap(null);
//异步任务请求图片
new MyAsyncTask(new MyBitmapCallBack(viewHolder.imageView)).execute(dataBean.getTitlepic());
return convertView;
}
static class ViewHolder {
ImageView imageView;
TextView title;
TextView step;
TextView taste;
RatingBar rat;
}
}
MyBitmapCallBack.java
public class MyBitmapCallBack implements ModelInter.OnDataCompleteListener {
private ImageView mImg;
//将对应的图片控件传递过来
public MyBitmapCallBack(ImageView mImg){
this.mImg = mImg;
}
/**
* 当网络数据请求完成后,会调用这个方法,获取图片数据
* @param bytes 图片数据
* @param path 对应的图片地址
*/
@Override
public void onLoadComplete(byte[] bytes, String path) {
String tag = (String) mImg.getTag();
//判断当前下载的图片地址是否和每次显示的图片地址是否相同
if(bytes != null && tag.equals(path)){
//将字节数组转换成Bitmap
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
//设置图片
mImg.setImageBitmap(bitmap);
}
}
}
好了,整体的实现都已经完成了,除了实体类HotFoodBean没有写上去之外,其他的功能都已经实现了,
可能对于初学者来说,接口回调的形式有点绕,如果当中有不懂的知识点,可以在我的博客中学习对应的知识点。
最后添加上Bean实体类
HotFoodBean .java
public class HotFoodBean {
/**
* title : 热菜有关的菜谱:
* classname : 热菜
* classid : 6
* total : 46190
* header_img : http://static.meishij.net/images/mobileimg/recai1.jpg
* header_word :
* classes : [{"title":"热菜","id":"6"},{"title":"凉菜","id":"5"},{"title":"素菜","id":"74"},{"title":"靓汤","id":"388"},{"title":"粥品","id":"389"},{"title":"主食","id":"390"},{"title":"点心","id":"272"},{"title":"卤味","id":"273"},{"title":"微波炉","id":"11"},{"title":"海鲜","id":"75"},{"title":"火锅","id":"59"},{"title":"酱料蘸料","id":"343"},{"title":"干果零食","id":"77"},{"title":"饮品","id":"57"},{"title":"孕妇","id":"62"},{"title":"产妇","id":"72"},{"title":"宝宝","id":"12"},{"title":"老人","id":"73"},{"title":"美容","id":"58"},{"title":"瘦身","id":"61"}]
* data : [{"id":"20440","title":"口水鱼片","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:花鲢鱼一条,淀粉两大匙,油炸花生仁约半两,熟","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"209364","title":"烤甜椒塞肉","titlepic":"http://images.meishij.net/p/20111121/a10388301b285e12d5083b7a1816c963_150x150.jpg","gongyi":"烤","kouwei":"咸鲜味","md":"初级入门","mt":"<15分钟","step":"4","smalltext":"出炉后的甜椒还是很可爱很完整,装入垫了从阳台上采下的生菜叶的盘内,淋上甜辣酱,久久不舍下箸。拍完几张片子后,差...","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"20569","title":"白宰鸡","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:鸡,色拉油,盐,辣椒粉,花椒粉,十三香,鸡精","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"615392","title":"珊瑚雪花鸡","titlepic":"http://site.meishij.net/r/209/172/1418209/a1418209_78049.jpg","gongyi":"蒸","kouwei":"咸鲜味","md":"初中水平","mt":"<60分钟","step":"15","smalltext":"珊瑚雪花鸡","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"52230","title":"佛手排骨的做法","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"原料:排骨400克,瘦猪肉300克,虾肉50克,鸭蛋2个,肥猪肉25克,生葱50克,荸荠50克,","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"39647","title":"蜜桃鲜贝杏仁卷的做法","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"材料:水蜜桃2个、鲜贝6个、杏仁片100克、糯米纸6张调味料:沙拉酱2大匙、鸡蛋1个、太白","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"19368","title":"红烧大虾","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"烧","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:大对虾4对(约重1000克左右)白糖75克、鸡汤150","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"537245","title":"梭子蟹炖蛋","titlepic":"http://images.meishij.net/p/20101013/3d67d358fe4ce82a92bb7036217abc90.jpg","gongyi":"炖","kouwei":"咸鲜味","md":"","mt":"","step":"2","smalltext":"梭子蟹炖蛋","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"20496","title":"韭菜皮蛋松","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:主料:韭菜花辅料:瘦猪肉、皮蛋调","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"6494","title":"剁椒香煎豆腐","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"煎","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:老豆腐、剁椒、小葱末、盐、醋、生抽、鸡精","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0}]
* is_filter : 1
* search_num : 624440
* column_rank : 3
* city_hot : 北京市
*/
private ObjBean obj;
/**
* obj : {"title":"热菜有关的菜谱:","classname":"热菜","classid":"6","total":"46190","header_img":"http://static.meishij.net/images/mobileimg/recai1.jpg","header_word":"","classes":[{"title":"热菜","id":"6"},{"title":"凉菜","id":"5"},{"title":"素菜","id":"74"},{"title":"靓汤","id":"388"},{"title":"粥品","id":"389"},{"title":"主食","id":"390"},{"title":"点心","id":"272"},{"title":"卤味","id":"273"},{"title":"微波炉","id":"11"},{"title":"海鲜","id":"75"},{"title":"火锅","id":"59"},{"title":"酱料蘸料","id":"343"},{"title":"干果零食","id":"77"},{"title":"饮品","id":"57"},{"title":"孕妇","id":"62"},{"title":"产妇","id":"72"},{"title":"宝宝","id":"12"},{"title":"老人","id":"73"},{"title":"美容","id":"58"},{"title":"瘦身","id":"61"}],"data":[{"id":"20440","title":"口水鱼片","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:花鲢鱼一条,淀粉两大匙,油炸花生仁约半两,熟","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"209364","title":"烤甜椒塞肉","titlepic":"http://images.meishij.net/p/20111121/a10388301b285e12d5083b7a1816c963_150x150.jpg","gongyi":"烤","kouwei":"咸鲜味","md":"初级入门","mt":"<15分钟","step":"4","smalltext":"出炉后的甜椒还是很可爱很完整,装入垫了从阳台上采下的生菜叶的盘内,淋上甜辣酱,久久不舍下箸。拍完几张片子后,差...","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"20569","title":"白宰鸡","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:鸡,色拉油,盐,辣椒粉,花椒粉,十三香,鸡精","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"615392","title":"珊瑚雪花鸡","titlepic":"http://site.meishij.net/r/209/172/1418209/a1418209_78049.jpg","gongyi":"蒸","kouwei":"咸鲜味","md":"初中水平","mt":"<60分钟","step":"15","smalltext":"珊瑚雪花鸡","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"52230","title":"佛手排骨的做法","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"原料:排骨400克,瘦猪肉300克,虾肉50克,鸭蛋2个,肥猪肉25克,生葱50克,荸荠50克,","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"39647","title":"蜜桃鲜贝杏仁卷的做法","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"材料:水蜜桃2个、鲜贝6个、杏仁片100克、糯米纸6张调味料:沙拉酱2大匙、鸡蛋1个、太白","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"19368","title":"红烧大虾","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"烧","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:大对虾4对(约重1000克左右)白糖75克、鸡汤150","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"537245","title":"梭子蟹炖蛋","titlepic":"http://images.meishij.net/p/20101013/3d67d358fe4ce82a92bb7036217abc90.jpg","gongyi":"炖","kouwei":"咸鲜味","md":"","mt":"","step":"2","smalltext":"梭子蟹炖蛋","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"20496","title":"韭菜皮蛋松","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:主料:韭菜花辅料:瘦猪肉、皮蛋调","is_recipe":0,"item_type":"0","rate":"3","is_video":"0","is_fav":0,"is_see":0},{"id":"6494","title":"剁椒香煎豆腐","titlepic":"http://css.meishij.net/images/nopic_150.gif","gongyi":"煎","kouwei":"","md":"","mt":"","step":0,"smalltext":"·配料:老豆腐、剁椒、小葱末、盐、醋、生抽、鸡精","is_recipe":1,"item_type":"1","rate":"3","is_video":"0","is_fav":0,"is_see":0}],"is_filter":"1","search_num":624440,"column_rank":"3","city_hot":"北京市"}
* code : 1
* msg : 成功
*/
private String code;
private String msg;
public ObjBean getObj() {
return obj;
}
public void setObj(ObjBean obj) {
this.obj = obj;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public static class ObjBean {
private String title;
private String classname;
private String classid;
private String total;
private String header_img;
private String header_word;
private String is_filter;
private int search_num;
private String column_rank;
private String city_hot;
/**
* title : 热菜
* id : 6
*/
private List classes;
/**
* id : 20440
* title : 口水鱼片
* titlepic : http://css.meishij.net/images/nopic_150.gif
* gongyi :
* kouwei :
* md :
* mt :
* step : 0
* smalltext : ·配料:花鲢鱼一条,淀粉两大匙,油炸花生仁约半两,熟
* is_recipe : 0
* item_type : 0
* rate : 3
* is_video : 0
* is_fav : 0
* is_see : 0
*/
private List data;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
public String getClassid() {
return classid;
}
public void setClassid(String classid) {
this.classid = classid;
}
public String getTotal() {
return total;
}
public void setTotal(String total) {
this.total = total;
}
public String getHeader_img() {
return header_img;
}
public void setHeader_img(String header_img) {
this.header_img = header_img;
}
public String getHeader_word() {
return header_word;
}
public void setHeader_word(String header_word) {
this.header_word = header_word;
}
public String getIs_filter() {
return is_filter;
}
public void setIs_filter(String is_filter) {
this.is_filter = is_filter;
}
public int getSearch_num() {
return search_num;
}
public void setSearch_num(int search_num) {
this.search_num = search_num;
}
public String getColumn_rank() {
return column_rank;
}
public void setColumn_rank(String column_rank) {
this.column_rank = column_rank;
}
public String getCity_hot() {
return city_hot;
}
public void setCity_hot(String city_hot) {
this.city_hot = city_hot;
}
public List getClasses() {
return classes;
}
public void setClasses(List classes) {
this.classes = classes;
}
public List getData() {
return data;
}
public void setData(List data) {
this.data = data;
}
public static class ClassesBean {
private String title;
private String id;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
public static class DataBean {
private String id;
private String title;
private String titlepic;
private String gongyi;
private String kouwei;
private String md;
private String mt;
private int step;
private String smalltext;
private int is_recipe;
private String item_type;
private String rate;
private String is_video;
private int is_fav;
private int is_see;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitlepic() {
return titlepic;
}
public void setTitlepic(String titlepic) {
this.titlepic = titlepic;
}
public String getGongyi() {
return gongyi;
}
public void setGongyi(String gongyi) {
this.gongyi = gongyi;
}
public String getKouwei() {
return kouwei;
}
public void setKouwei(String kouwei) {
this.kouwei = kouwei;
}
public String getMd() {
return md;
}
public void setMd(String md) {
this.md = md;
}
public String getMt() {
return mt;
}
public void setMt(String mt) {
this.mt = mt;
}
public int getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
public String getSmalltext() {
return smalltext;
}
public void setSmalltext(String smalltext) {
this.smalltext = smalltext;
}
public int getIs_recipe() {
return is_recipe;
}
public void setIs_recipe(int is_recipe) {
this.is_recipe = is_recipe;
}
public String getItem_type() {
return item_type;
}
public void setItem_type(String item_type) {
this.item_type = item_type;
}
public String getRate() {
return rate;
}
public void setRate(String rate) {
this.rate = rate;
}
public String getIs_video() {
return is_video;
}
public void setIs_video(String is_video) {
this.is_video = is_video;
}
public int getIs_fav() {
return is_fav;
}
public void setIs_fav(int is_fav) {
this.is_fav = is_fav;
}
public int getIs_see() {
return is_see;
}
public void setIs_see(int is_see) {
this.is_see = is_see;
}
}
}
}