Android app 用appBase快速开发购物车实例教程

appBase基础介绍

appBase是什么?

appBase是一个Android app开发的基础集合,目的是任何应用都可以在这个基础之上开发app,省去了搭建框架的时间。

appBase=xutils+fastjson+avlib

    xutils使用了其中HttpUtils、BitmapUtils、DbUtils
    fastjson使用了json解析
    avlib大家比较陌生,这个库是我另外一个简单的工具库。主要功能是View的自动绑定、View的常用数据自动绑定、万能Adapter等

目的:是为了让懂java的同学能够快速上手Android开发。

一、看看框架结构

- apicloud.sdk是对apicloud的云API的调用做了简单封装
- base:只包含BaseActivity
- http:基于HttpUtils简化了常用的网络请求,定义网络参数APIs的配置
- presenter:采用了MVP中的P来命名,可以让非UI处理业务抽出放到这个结构中,因此BasePresenter诞生了。
- util:常用的工具类
- widget:常用的自定义组件(待扩展)
- Application:继承android.app.Application,为了统一使用框架中的组件对象,避免了组件的重复创建。因此建议使用这个类配置application的name。当然也可以基于此类扩展。

二、创建一个新项目

    第一步:创建一个空的Android project
    技术分享
    注意:删除自动添加的android-support-v4.jar(appBase中包含有)
    第二步:引用appBase
    技术分享

    第三步:修改AndroidManifest.xml

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.snicesoft.appbase.demo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:name="com.snicesoft.Application"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
    </application>
    </manifest>

    添加:android:name=”com.snicesoft.Application”

    第四步:创建Activity

    package com.snicesoft.appbase.demo;
    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> {
        public class Holder extends IHolder {

            @Override
            public void initViewParams() {

            }

        }

        public class Data extends IData {

        }

        @Override
        public Data newData() {
            return new Data();
        }

        @Override
        public Holder newHolder() {
            return new Holder();
        }
    }

    看着class一栏,大家可能会花了眼,怎么这么长。这只是一种写法,推荐的写法(内部类)。我来说明下这个类:
    IHolder是指View自动绑定的容器
    IData是指View的数据自动绑定容器

    第五步:使用IHolder和IData

    package com.snicesoft.appbase.demo;
    import com.snicesoft.avlib.annotation.DataBind;
    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> {
        public class Holder extends IHolder {
            @Id(R.id.textView1)
            TextView textView1;
            @Id(R.id.button1)
            Button button1;
            @Override
            public void initViewParams() {

            }

        }

        public class Data extends IData {
            @DataBind(id = R.id.textView1)
            String tv1 = "我是自动绑定的TextView";
            @DataBind(id = R.id.button1)
            String btn1 = "我是自动绑定的Button";
        }

        @Override
        public Data newData() {
            return new Data();
        }

        @Override
        public Holder newHolder() {
            return new Holder();
        }
    }

    运行结果

Android appBase 购物车开发

购物车,在商城app中是必不可少的一部分,也是使用的比较多的,这里简单的做一个效果。

先来看看效果图

1、创建项目

第一种、引用appBase项目即可
第二种、将appBase的jar文件copy到libs下

我用的第二种,如上图所示。

2、代码生成

通过代码生成器生成Activity、Presenter、Adapter

1、生成Activity(默认生成Presenter)


2、生成Adapter


3、网络请求数据

这里网络数据使用的是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无法正常解析,会导致无法反射创建对象。

4、数据绑定和交互

首先看下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的依据)

开发思路我们就讲得差不多了,做开发,最重要的还是思路,整体代码我们就不给出了,有兴趣的朋友可以自己整理代码,加深印象。

时间: 2024-08-28 04:48:34

Android app 用appBase快速开发购物车实例教程的相关文章

Android App中自定义View视图的实例教程_Android

一.基础很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章.先总结下自定义View的步骤: 1.自定义View的属性 2.在View的构造方法中获得我们自定义的属性 3.重写onMesure 4.重写onDraw 我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是需要重写的. 1.自定义View的属性,首先在res/values/  下建立一个attrs.xml

Android App中自定义View视图的实例教程

一.基础 很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章.先总结下自定义View的步骤: 1.自定义View的属性 2.在View的构造方法中获得我们自定义的属性 3.重写onMesure 4.重写onDraw 我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是需要重写的. 1.自定义View的属性,首先在res/values/  下建立一个attrs.xm

app-Android App开发完整实例教程谁有?急求大神大神指导,新手求学。非常感谢

问题描述 Android App开发完整实例教程谁有?急求大神大神指导,新手求学.非常感谢 Android App开发完整实例教程谁有?急求大神大神指导,新手求学.非常感谢. 解决方案 先看一遍书吧,可以参考<精通Android4编程>或者<疯狂Android讲义>,然后可以上http://edu.csdn.net/?ref=toolbar CSDN学院看看. 解决方案二: 我之前博客分享的半成品:http://blog.csdn.net/gao_chun/article/deta

Android App增量更新详解及实例代码_Android

Android App增量更新实例--Smart App Updates        介绍 你所看到的,是一个用于Android应用程序增量更新的开源库. 包括客户端.服务端两部分代码. 原理 自从 Android 4.1 开始,Google引入了应用程序的增量更新. Link: http://developer.android.com/about/versions/jelly-bean.html Smart app updates is a new feature of Google Pla

Android App调用MediaRecorder实现录音功能的实例_Android

MediaRecorder Android的MediaRecorder包含了Audio和video的记录功能,在Android的界面上,Music和Video两个应用程序都是调用MediaRecorder实现的. MediaRecorder在底层是基于OpenCore(PacketVideo)的库实现的,为了构建一个MediaRecorder程序,上层还包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制. 以开源的Android为例MediaRecorder的

Android App调用MediaRecorder实现录音功能的实例

MediaRecorder Android的MediaRecorder包含了Audio和video的记录功能,在Android的界面上,Music和Video两个应用程序都是调用MediaRecorder实现的. MediaRecorder在底层是基于OpenCore(PacketVideo)的库实现的,为了构建一个MediaRecorder程序,上层还包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制. 以开源的Android为例MediaRecorder的

Android App增量更新详解及实例代码

Android App增量更新实例--Smart App Updates 介绍 你所看到的,是一个用于Android应用程序增量更新的开源库. 包括客户端.服务端两部分代码. 原理 自从 Android 4.1 开始,Google引入了应用程序的增量更新. Link: http://developer.android.com/about/versions/jelly-bean.html Smart app updates is a new feature of Google Play that

用于Android App安全检测Drozer工具安装使用教程

最近接到任务,让了解一下几款Android安全测试相关的软件,首先是Drozer.Drozer是一款综合的安全评估和攻击的android框架,据 产品介绍 里说,Drozer可以全面评估app的安全性,并帮助团队把app的安全风险保持在可控范围内. 使用方法 1.在 mwrinfosecurity 公司的这个网页上,提供了社区版本的下载(没错,还有收费的高级版),下载并安装之.并保证android的adb环境已经配置好,即cmd中输入adb devices不会报错.并在手机端安装下载包中的Age

Illustrator简单快速绘制蜂鸟实例教程分享

给各位Illustrator软件的使用者们来详细的解析分享一下简单快速绘制蜂鸟的实例教程. 教程分享: 先看看"蜂鸟"的图层分解,好了解制作思路.   接下来是局部分解图:先是身体的分解图(有点眼花,呵呵*^*)   下面是 身体的轮廓预览图   然后是右边的 翅膀 分解图   右翅的轮廓预览图   接着是左边的 翅瓣 分解图   左边 翅瓣 轮廓预览图   再接着是尖尖的小嘴巴!   轮廓预览   最后是点睛之笔 眼睛   轮廓预览图   效果图   好了,以上的信息就是小编给各位I