转载请注明本文出自JFlex的博客http://blog.csdn.net/jflex/article/details/46653309,请尊重他人的辛勤劳动成果,谢谢!
最近将appBase实战于各种项目中,也发现了不少问题,并优化了很多功能。今天带给大家一个实战–《购物车》。购物车,在商城app中是必不可少的一部分,也是使用的比较多的,这里简单的做一个效果。
先来看看效果图
我用的第二种,如上图所示。
通过代码生成器生成Activity、Presenter、Adapter
这里网络数据使用的是APICloud,那么就需要对于APICloudSDK进行配置。最新的appBase讲配置放了出来,只要在applcation中进行代码配置就可以了。
package com.example.shopcartdemo;
import com.apicloud.sdk.APICloudSDK;
import com.snicesoft.Application;
import com.snicesoft.http.HttpReq;
public class MyApplication extends Application {
final String APP_ID = "A6960031839242";
final String APP_KEY = "3F248D5F-50DB-782A-F437-E13796238B9E";
@Override
public void onCreate() {
super.onCreate();
APICloudSDK.getInstance().init(APP_ID, APP_KEY);
APICloudSDK.getInstance().init(hu());
HttpReq.debug = true;
}
}
这里添加了DialogPresenter,作用就是为了请求的时候对dialog的控制
DialogPresenter
package com.example.shopcartdemo.presenter;
import android.app.ProgressDialog;
import android.content.Context;
import com.snicesoft.presenter.BasePresenter;
import com.snicesoft.util.DialogUtil;
public class DialogPresenter<C extends BasePresenter.Callback> extends
BasePresenter<C> {
public DialogPresenter(Context context) {
super(context);
progressDialog = DialogUtil.getProgressDialog(context);
}
ProgressDialog progressDialog;
protected void showDialog(CharSequence message, boolean... flag) {
if (flag != null) {
if (flag.length > 0)
progressDialog.setCancelable(flag[0]);
if (flag.length > 1)
progressDialog.setCanceledOnTouchOutside(flag[1]);
}
progressDialog.setMessage(message);
if (!progressDialog.isShowing())
progressDialog.show();
}
protected void closeDialog() {
if (progressDialog.isShowing())
progressDialog.dismiss();
}
}
MainPresenter
package com.example.shopcartdemo.presenter;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import com.alibaba.fastjson.JSON;
import com.apicloud.sdk.APICloudSDK;
import com.example.shopcartdemo.adapter.ShopCartAdapter;
import com.lidroid.xutils.exception.HttpException;
import com.snicesoft.http.HttpCallback;
import com.snicesoft.presenter.BasePresenter;
import com.snicesoft.util.CommonUtils;
public class MainPresenter extends DialogPresenter<MainPresenter.Callback> {
public MainPresenter(Context context) {
super(context);
}
public interface Callback extends BasePresenter.Callback {
void setShopCartList(List<ShopCartAdapter.Data> list);
}
public static class ShopCart {
String title;
int price;
int count;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
public void getShopCartList() {
showDialog("正在加载");
APICloudSDK
.getInstance()
.GET("/mcm/api/ShopCart?filter=%7B%22where%22%3A%7B%7D%2C%22skip%22%3A0%2C%22limit%22%3A20%7D",
null, new HttpCallback() {
@Override
public void onSuccess(String result) {
closeDialog();
List<ShopCart> array = JSON.parseArray(result,
ShopCart.class);
List<ShopCartAdapter.Data> list = new ArrayList<ShopCartAdapter.Data>();
for (ShopCart cart : array) {
list.add(new ShopCartAdapter.Data(
0,
cart.title,
cart.price,
"http://ck.haier.com/UpLoad/2015-05-15/a5e8cac4-2671-4aa0-83a7-66c64e051f95.jpg",
cart.count));
}
if (callback != null)
callback.setShopCartList(list);
}
@Override
public void onFailure(HttpException arg0) {
closeDialog();
CommonUtils.showToast(getContext(), "请求失败,请稍后重试");
}
});
}
}
在这个类中,网络请求和网络解析实体对象都用内部类来定义,注意:内部类定义一定要用static class,否则fastjson无法正常解析,会导致无法反射创建对象。
首先看下Activity
package com.example.shopcartdemo;
import java.util.List;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import com.example.shopcartdemo.adapter.ShopCartAdapter;
import com.example.shopcartdemo.adapter.ShopCartAdapter.ViewCallback;
import com.example.shopcartdemo.presenter.MainPresenter;
import com.snicesoft.avlib.annotation.DataBind;
import com.snicesoft.avlib.annotation.DataType;
import com.snicesoft.avlib.annotation.Id;
import com.snicesoft.avlib.annotation.Layout;
import com.snicesoft.avlib.rule.IData;
import com.snicesoft.avlib.rule.IHolder;
import com.snicesoft.base.BaseActivity;
@Layout(R.layout.activity_main)
public class MainActivity extends
BaseActivity<MainActivity.Holder, MainActivity.Data> implements
MainPresenter.Callback, ViewCallback {
class Holder extends IHolder {
@Id(R.id.lvShopCard)
ListView lvShopCard;
@Id(R.id.cbAll)
CheckBox cbAll;
@Id(R.id.tvPrice)
TextView tvPrice;
@Override
public void initViewParams() {
cbAll.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
_data.shopCartAdapter.setAll(cbAll.isChecked());
tvPrice.setText("¥" + _data.shopCartAdapter.calc());
}
});
}
}
class Data extends IData {
@DataBind(id = R.id.lvShopCard, dataType = DataType.ADAPTER)
ShopCartAdapter shopCartAdapter = new ShopCartAdapter(getBaseContext());
}
@Override
public Holder newHolder() {
return new Holder();
}
@Override
public Data newData() {
return new Data();
}
MainPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
presenter = new MainPresenter(this);
presenter.setCallback(this);
_data.shopCartAdapter.setCallback(this);
}
@Override
protected void onResume() {
super.onResume();
presenter.getShopCartList();
}
@Override
public void onClick(View v) {
super.onClick(v);
switch (v.getId()) {
case R.id.btnGoPay:
break;
case R.id.btnDelete:
break;
default:
break;
}
}
boolean isNormal = true;
@Override
public void setShopCartList(List<ShopCartAdapter.Data> list) {
_data.shopCartAdapter.setDataList(list);
refreshView();
}
@Override
public void refreshView() {
_holder.cbAll.setChecked(_data.shopCartAdapter.isAll());
_holder.tvPrice.setText("¥" + _data.shopCartAdapter.calc());
}
}
基本的Holder和Data将组件和数据进行简单的管理,清晰可见。
presenter将业务进行分离,将传统的activity中请求数据进行分离。
ViewCallback这个类是为了解决Adapter与Activity直接的交互定义的接口。
接下来看看Adapter
package com.example.shopcartdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import com.example.shopcartdemo.R;
import com.snicesoft.avlib.AVLib;
import com.snicesoft.avlib.annotation.DataBind;
import com.snicesoft.avlib.annotation.DataType;
import com.snicesoft.avlib.annotation.Id;
import com.snicesoft.avlib.annotation.Layout;
import com.snicesoft.avlib.rule.IData;
import com.snicesoft.avlib.rule.IHolder;
import com.snicesoft.avlib.view.ViewFinder;
import com.snicesoft.avlib.widget.AvAdapter;
@Layout(R.layout.item_shopcart)
public class ShopCartAdapter extends
AvAdapter<ShopCartAdapter.Holder, ShopCartAdapter.Data> {
public ShopCartAdapter(Context context) {
super(context);
}
class Holder extends IHolder {
@Id(R.id.btnAdd)
Button btnAdd;
@Id(R.id.btnDelete)
Button btnDelete;
@Id(R.id.cbSelect)
CheckBox cbSelect;
@Id(R.id.img)
ImageView img;
@Override
public void initViewParams() {
}
}
public static class Data extends IData {
long gid;
boolean isChecked = true;
public long getGid() {
return gid;
}
@DataBind(id = R.id.tvTitle)
String title;
@DataBind(id = R.id.tvPrice, prefix = "¥")
int price;
@DataBind(id = R.id.img, dataType = DataType.IMG)
String image;
@DataBind(id = R.id.edtCount)
int count;
public Data(long gid, String title, int price, String image, int count) {
super();
this.gid = gid;
this.title = title;
this.price = price;
this.image = image;
this.count = count;
}
}
public interface ViewCallback {
void refreshView();
}
ViewCallback callback;
public void setCallback(ViewCallback callback) {
this.callback = callback;
}
@Override
public Holder newHolder() {
return new Holder();
}
@Override
public void bindAfter(int position, final View view, Holder holder,
final Data data) {
holder.cbSelect.setOnCheckedChangeListener(null);
holder.cbSelect.setChecked(data.isChecked);
holder.btnAdd.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
data.count++;
AVLib.dataBindTo(data, new ViewFinder(view), "count");
if (callback != null)
callback.refreshView();
}
});
holder.btnDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (data.count > 1) {
data.count--;
AVLib.dataBindTo(data, new ViewFinder(view), "count");
if (callback != null)
callback.refreshView();
}
}
});
holder.cbSelect
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
data.isChecked = isChecked;
if (callback != null)
callback.refreshView();
}
});
}
public void setAll(boolean isChecked) {
for (Data data : getDataList()) {
data.isChecked = isChecked;
}
notifyDataSetChanged();
}
public int calc() {
int total = 0;
for (Data data : getDataList()) {
if (data.isChecked)
total += data.count * data.price;
}
return total;
}
public boolean isAll() {
for (Data data : getDataList()) {
if (!data.isChecked)
return false;
}
return true;
}
}
Holder的组件定义原则:需要在当前所在类中调用即可定义
Data的DataBind使用原则:需要绑定的的组件都可以。
当然通过上面可以看出Data中可以定义不用DataBind注解的字段,这个替代了传统的辅助Map或者List解决一些问题。
在上面的Data中用isChecked来表示CheckBox是否选中。这个问题,在我刚开始写android的时候,常常会用Map集合将position对应的boolean值记录下来,然后在getView中去检测。现在可以简单的通过Data几种管理,使得Adapter的字段不需要那么繁琐。
对于isChecked的使用产生了下面3个业务方法
setAll:这个方法用来设置全部选中(Activity中的全选按钮事件)
calc:这个方法用来计算购物车总额(Activity中的总计)
isAll:这个方法用来判断是否全部被选中(Activity的全选按钮设置checked的依据)
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/jflex/article/details/46653309