Okhttp封装 , 运用单利

public class OkhttpsUtil {
    private OkHttpClient client;
    private static OkhttpsUtil okhttpsUtil;
    private Handler handler;
    private OkhttpsUtil(){
        handler = new Handler(Looper.getMainLooper());
        //拦截类
        Okhttplan okhttplan = new Okhttplan();
        client = new OkHttpClient.Builder()
        //添加拦截类
                .addInterceptor(okhttplan)
                .writeTimeout(5,TimeUnit.SECONDS)
                .readTimeout(5,TimeUnit.SECONDS)
                .connectTimeout(5,TimeUnit.SECONDS)
                .build();
    }
    public static OkhttpsUtil getIntense(){
        if (okhttpsUtil==null){
            synchronized (OkhttpsUtil.class){
                if (okhttpsUtil==null){
                    return okhttpsUtil = new OkhttpsUtil();
                }
            }

        }
        return okhttpsUtil;
    }

    public interface OkCallBack{
        void cheng(String json);
        void bai(Exception e);
    }

    public void doPost(String path, Map<String,String> map, final OkCallBack lkOkCallBak){
        FormBody.Builder builder = new FormBody.Builder();
        if(map!=null){
            for(String key: map.keySet()){
                builder.add(key,map.get(key));
            }
        }
        FormBody formBody = builder.build();

        Request request = new Request.Builder()
                .post(formBody)
                .url(path)
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                if (lkOkCallBak!=null){
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                                 lkOkCallBak.bai(e);
                        }
                    });
                }
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                try{
                    if (lkOkCallBak!=null&&response.isSuccessful()){
                        final String json = response.body().string();
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                lkOkCallBak.cheng(json);
                            }
                        });
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
                if (lkOkCallBak != null) {
                    lkOkCallBak.bai(new Exception("网络异常"));
                }

            }
        });
    }
}

OkHtpp拦截器

//继承Interceptor
public class Okhttplan implements Interceptor {
    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        //拿到Request对象
        Request request = chain.request();

        long t1 = System.nanoTime();
        System.out.println(" request  = " + String.format("Sending request %s on %s%n%s",
                request.url(), chain.connection(), request.headers()));

        //拿到Response对象
        Response response = chain.proceed(request);

        long t2 = System.nanoTime();
        //得出请求网络,到得到结果,中间消耗了多长时间
        System.out.println("response  " + String.format("Received response for %s in %.1fms%n%s",
                response.request().url(), (t2 - t1) / 1e6d, response.headers()));
        return response;
    }
}

主页面布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <ExpandableListView
        android:id="@+id/ex1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        ></ExpandableListView>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_alignParentBottom="true"
        android:background="#eeeeee"
        android:gravity="center_vertical">

        <CheckBox
            android:id="@+id/cb_cart_all_select"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="全选" />

        <TextView
            android:id="@+id/tv_cart_total_price"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:paddingLeft="20dp"
            android:text="合计:¥0.00" />

        <Button
            android:id="@+id/btn_cart_pay"
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:text="去结算(0)" />
    </LinearLayout>

</LinearLayout>

商家布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:gravity="center_vertical"
    >


    <CheckBox
        android:id="@+id/seller_cb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/seller_name_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp" />
</LinearLayout>

商品布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="120dp"
    android:gravity="center_vertical">

    <CheckBox
        android:id="@+id/child_cb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/product_icon_iv"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginLeft="20dp"
        android:scaleType="centerCrop"
        android:src="@color/colorPrimary" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/product_title_name_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="2"
            android:text="商品标题" />

        <TextView
            android:id="@+id/product_price_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="¥0.0" />
    </LinearLayout>
	//自定义组件
    <bwei.com.fengxiangbin.day18.MyAddSubView
        android:id="@+id/add_remove_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp" />
</LinearLayout>

自定义View组件布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:padding="2dp"
    android:layout_marginLeft="10dp"
    android:layout_width="60dp"
    android:layout_height="30dp"
    android:layout_gravity="center_vertical"
    android:background="#99000000"
    android:gravity="center_vertical">

    <TextView
        android:background="#ffffff"
        android:layout_weight="1"
        android:id="@+id/sub_tv"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="-"
        android:textSize="16sp" />

    <TextView
        android:text="1"
        android:layout_marginLeft="2dp"
        android:background="#ffffff"
        android:layout_weight="1"
        android:id="@+id/product_number_tv"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:gravity="center"
       />

    <TextView
        android:layout_marginLeft="2dp"
        android:background="#ffffff"
        android:layout_weight="1"
        android:id="@+id/add_tv"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="+"
        android:textSize="16sp" />

</LinearLayout>

自定义组件代码实现

public class MyAddSubView extends LinearLayout implements View.OnClickListener {
    private int number = 1;
    private TextView sub_tv;
    private TextView product_number_tv;
    private TextView add_tv;
    public MyAddSubView(Context context) {
        this(context,null);
    }

    public MyAddSubView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MyAddSubView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        View view = inflate(context, R.layout.add_remove_view_layout, this);

        sub_tv=view.findViewById(R.id.sub_tv);
        product_number_tv=view.findViewById(R.id.product_number_tv);
        add_tv=view.findViewById(R.id.add_tv);


        sub_tv.setOnClickListener(this);
        add_tv.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.sub_tv:
                if (number > 1) {
                    --number;
                    product_number_tv.setText(number + "");
                    if (onNumberChangeListener != null) {
                        onNumberChangeListener.onNumberChange(number);
                    }
                } else {
                    Toast.makeText(getContext(), "不能再少了", Toast.LENGTH_SHORT).show();
                }
                break;


            case R.id.add_tv:
                ++number;
                product_number_tv.setText(number + "");
                if (onNumberChangeListener != null) {
                    onNumberChangeListener.onNumberChange(number);
                }
                break;
        }

    }
    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
        product_number_tv.setText(number + "");
    }

    OnNumberChangeListener onNumberChangeListener;

    public void setOnNumberChangeListener(OnNumberChangeListener onNumberChangeListener) {
        this.onNumberChangeListener = onNumberChangeListener;
    }

    interface OnNumberChangeListener {
        void onNumberChange(int num);
    }
}

自定义主件效果如下
购物车练习
MainCtivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    ExpandableListView ex1;
    Button bt1;
    TextView tx1;
    CheckBox cb;
    NewsAdaptre adapter;
    String url = "http://www.zhaoapi.cn/product/getCarts";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
    }

    private void initData() {
        HashMap<String,String> map = new HashMap<>();
        map.put("uid","71");
        OkhttpsUtil.getIntense().doPost(url, map, new OkhttpsUtil.OkCallBack() {
            @Override
            public void cheng(String json) {
               NewsBean newsBean= new Gson().fromJson(json,NewsBean.class);
               if ("0".equals(newsBean.getCode())){
                  List<NewsBean.DataBean> li = newsBean.getData();
                   adapter = new NewsAdaptre((ArrayList<NewsBean.DataBean>) li);
                   // //可以先不写,先写出主要效果,这是加减号点击,多选框点击效果
                   **adapter.setOnCartListChangeListener(new NewsAdaptre.onCartListChangeListener() {
                       @Override
                       public void onSellerCheckedChange(int groupPosition) {
                           boolean cur = adapter.isCurrentSellerAllProductSelected(groupPosition);
                           adapter.changeCurrentSellerAllProductsStatus(groupPosition,!cur);
                           adapter.notifyDataSetChanged();
                           refreshSelectedAndTotalPriceAndTotalNumber();
                       }
                       @Override
                       public void onProductCheckedChange(int groupPosition, int childPosition) {
                           adapter.changeCurrentProductStatus(groupPosition,childPosition);
                            adapter.notifyDataSetChanged();
                            refreshSelectedAndTotalPriceAndTotalNumber();
                       }
                       @Override
                       public void onProducNumberChange(int groupPosition, int childPosition, int number) {
                           adapter.changeCurrentProductNumber(groupPosition,childPosition,number);
                           adapter.notifyDataSetChanged();
                           refreshSelectedAndTotalPriceAndTotalNumber();
                       }
                   });**
                    ex1.setAdapter(adapter);
                    for(int i=0;i<li.size();i++){
                        ex1.expandGroup(i);
                    }
               }
            }

            @Override
            public void bai(Exception e) {

            }
        });
    }

    private void initView() {
        ex1 = findViewById(R.id.ex1);
        bt1 = findViewById(R.id.btn_cart_pay);
        tx1 = findViewById(R.id.tv_cart_total_price);
        cb = findViewById(R.id.cb_cart_all_select);
        bt1.setOnClickListener(this);
        cb.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_cart_pay:
                break;
                 //可以先不写,先写出主要效果,这是全选按钮
            case R.id.cb_cart_all_select:
                boolean all = adapter.isAllProductsSelected();
                adapter.changeAllProductStatus(!all);
                adapter.notifyDataSetChanged();
                refreshSelectedAndTotalPriceAndTotalNumber();
                break;
        }
    }
    //可以先不写,先写出主要效果
    private void refreshSelectedAndTotalPriceAndTotalNumber(){
        //去判断是否所有的商品都被选中
        boolean allProductsSelected = adapter.isAllProductsSelected();
        //把这个值设置给checkBox
        cb.setChecked(allProductsSelected);

        //计算总计
        float totalPrice = adapter.calculateTotalPrice();
        tx1.setText("总计"+totalPrice);

        //计算总数量
        int totalNumber = adapter.calculateTotalNumber();
        bt1.setText("去结算("+totalNumber+")");
    }
}

Adapter类

public class NewsAdaptre  extends BaseExpandableListAdapter {
    private ArrayList<NewsBean.DataBean> list ;
    public NewsAdaptre(ArrayList<NewsBean.DataBean> li) {
        list = li;
    }

    @Override//决定了有多少个组
    public int getGroupCount() {
        //三元运算符,提供程序运行效率
        return list == null ? 0 : list.size();
    }

    @Override//一个组里面有多少个子条目
    public int getChildrenCount(int groupPosition) {
        return list.get(groupPosition).getList() == null ? 0 : list.get(groupPosition).getList().size();
    }


    @Override
    public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        NewsBean.DataBean dataBean = list.get(groupPosition);
        ParentViewHolder parentViewHolder;
        if (convertView == null) {
            convertView = View.inflate(parent.getContext(), R.layout.item_cart_parent, null);
            parentViewHolder = new ParentViewHolder(convertView);
            convertView.setTag(parentViewHolder);
        } else {
            parentViewHolder = (ParentViewHolder) convertView.getTag();
        }
        parentViewHolder.seller_name_tv.setText(dataBean.getSellerName());
        //可以先不写,先写出主要效果
        *Boolean currentSellerAllProductSelected = isCurrentSellerAllProductSelected(groupPosition);
        parentViewHolder.seller_cb.setChecked(currentSellerAllProductSelected);
        parentViewHolder.seller_cb.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mOnCartListChangeListener!=null){
                    mOnCartListChangeListener.onSellerCheckedChange(groupPosition);
                }
            }
        });*
        return convertView;
    }


    @Override
    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
            NewsBean.DataBean dataBean = list.get(groupPosition);
            ArrayList<NewsBean.DataBean.ListBean> lis = (ArrayList<NewsBean.DataBean.ListBean>) dataBean.getList();
            NewsBean.DataBean.ListBean listBean = lis.get(childPosition);
            ChildViewHolder childViewHolder;
            if (convertView!=null){
                childViewHolder = (ChildViewHolder) convertView.getTag();
            }else{
                convertView = View.inflate(parent.getContext(), R.layout.item_cart_child, null);
                childViewHolder = new ChildViewHolder(convertView);
                convertView.setTag(childViewHolder);
            }
        //设置商品名字
        childViewHolder.product_title_name_tv.setText(listBean.getTitle());
        //设置商品单价
        childViewHolder.product_price_tv.setText(listBean.getPrice()+"");
        //设置复选框是否选中
        childViewHolder.child_cb.setChecked(listBean.getSelected() == 1);

        //设置组合式自定义控件内部的数量
        childViewHolder.add_remove_view.setNumber(listBean.getNum());
        ImageLoader.getInstance().displayImage(listBean.getImages(),childViewHolder.product_icon_iv);

        //设置自条目多选框点击事件
        //可以先不写,先写出主要效果
        *childViewHolder.child_cb.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mOnCartListChangeListener!=null){
                    mOnCartListChangeListener.onProductCheckedChange(groupPosition,childPosition);
                }
            }
        });
        childViewHolder.add_remove_view.setOnNumberChangeListener(new MyAddSubView.OnNumberChangeListener() {
            @Override
            public void onNumberChange(int num) {
                if (mOnCartListChangeListener!=null){
                    mOnCartListChangeListener.onProducNumberChange(groupPosition,childPosition,num);
                }
            }
        });* 
        returnconvertView;
    }
    //判断商家的商品是否被选中(两种情况,一全选,有没选中的)
  //可以先不写,先写出主要效果
    *public boolean isCurrentSellerAllProductSelected(int groupPosition){
        NewsBean.DataBean dataBean = list.get(groupPosition);
        ArrayList<NewsBean.DataBean.ListBean> li = (ArrayList<NewsBean.DataBean.ListBean>) dataBean.getList();
        for(NewsBean.DataBean.ListBean listBean :li){
            if (listBean.getSelected()==0){
                return false;
            }
        }
        return true;
    }
    //全选按钮
    public boolean isAllProductsSelected(){
        for(int i=0;i<list.size();i++){
            NewsBean.DataBean dataBean = list.get(i);
            ArrayList<NewsBean.DataBean.ListBean> li = (ArrayList<NewsBean.DataBean.ListBean>) dataBean.getList();
            for (int j=0;j<li.size();j++){
                if(li.get(j).getSelected()==0){
                    return false;
                }
            }
        }
        return true;
    }
    //计算商品的总量
    public int calculateTotalNumber(){
        int totalNumber = 0;
        for(int x=0;x<list.size();x++){
            NewsBean.DataBean dataBean = list.get(x);
            ArrayList<NewsBean.DataBean.ListBean> li = (ArrayList<NewsBean.DataBean.ListBean>) dataBean.getList();
            for(int j=0;j<li.size();j++){
                if(li.get(j).getSelected()==1){
                    int num=li.get(j).getNum();
                    totalNumber+=num;
                }
            }
        }
        return totalNumber;
    }
    //计算商品的价格
    public float calculateTotalPrice(){
        float totalPrice=0;
        for(int x  = 0;x<list.size();x++){
            NewsBean.DataBean dataBean = list.get(x);
            ArrayList<NewsBean.DataBean.ListBean> li = (ArrayList<NewsBean.DataBean.ListBean>) dataBean.getList();
            for(int j=0;j<li.size();j++){
                if(li.get(j).getSelected()==1){
                    float price = li.get(j).getPrice();
                    int num = li.get(j).getNum();
                    totalPrice+=price*num;
                }
            }
        }
        return totalPrice;
    }
    public void changeCurrentProductNumber(int groupPosition,int childPositon,int number){
        NewsBean.DataBean dataBean = list.get(groupPosition);
        ArrayList<NewsBean.DataBean.ListBean> li = (ArrayList<NewsBean.DataBean.ListBean>) dataBean.getList();
        NewsBean.DataBean.ListBean listBean = li.get(childPositon);
        listBean.setNum(number);
    }
    //当商品组全选点击时,更新状态
    public void changeCurrentSellerAllProductsStatus(int groupPosition , boolean isSelected){
        NewsBean.DataBean dataBean = list.get(groupPosition);
        ArrayList<NewsBean.DataBean.ListBean> li = (ArrayList<NewsBean.DataBean.ListBean>) dataBean.getList();
        for(int x=0;x<li.size();x++){
            NewsBean.DataBean.ListBean listBean1 = li.get(x);
            listBean1.setSelected(isSelected ? 1:0);
        }
    }
    //当子条目全选点击时
    public void changeCurrentProductStatus(int groupPosition , int childPositon){
        NewsBean.DataBean dataBean = list.get(groupPosition);
        ArrayList<NewsBean.DataBean.ListBean> li = (ArrayList<NewsBean.DataBean.ListBean>) dataBean.getList();
        NewsBean.DataBean.ListBean listBean = li.get(childPositon);
        listBean.setSelected(listBean.getSelected()==0?1:0);
    }
    //设置所有商品的状态
    public void changeAllProductStatus(Boolean selected){
        for(int i=0;i<list.size();i++){
            NewsBean.DataBean dataBean = list.get(i);
            ArrayList<NewsBean.DataBean.ListBean> li = (ArrayList<NewsBean.DataBean.ListBean>) dataBean.getList();
            for(int j=0;j<li.size();j++){
                li.get(j).setSelected(selected?1:0);
            }
        }
    }*
    public static class ParentViewHolder {
        public CheckBox seller_cb;
        public TextView seller_name_tv;

        public ParentViewHolder(View rootView) {
            this.seller_cb = (CheckBox) rootView.findViewById(R.id.seller_cb);
            this.seller_name_tv = (TextView) rootView.findViewById(R.id.seller_name_tv);
        }
    }
    public static class ChildViewHolder {
        public CheckBox child_cb;
        public ImageView product_icon_iv;
        public TextView product_title_name_tv;
        public TextView product_price_tv;
        public MyAddSubView add_remove_view;

        public ChildViewHolder(View rootView) {
            this.child_cb = (CheckBox) rootView.findViewById(R.id.child_cb);
            this.product_icon_iv = (ImageView) rootView.findViewById(R.id.product_icon_iv);
            this.product_title_name_tv = (TextView) rootView.findViewById(R.id.product_title_name_tv);
            this.product_price_tv = (TextView) rootView.findViewById(R.id.product_price_tv);
            this.add_remove_view = (MyAddSubView) rootView.findViewById(R.id.add_remove_view);
        }
    }
    public interface onCartListChangeListener{
        void onSellerCheckedChange(int groupPosition);
        void onProductCheckedChange(int groupPosition ,int childPosition);
        void onProducNumberChange(int groupPosition , int childPosition , int number);
    }
    //接口回调
    onCartListChangeListener mOnCartListChangeListener;
    //暴露方法
    public void setOnCartListChangeListener(onCartListChangeListener onCartListChangeListener){
        mOnCartListChangeListener = onCartListChangeListener ;
    }
    @Override//不管
    public boolean hasStableIds() {
        return false;
    }

    @Override//不管
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }


    @Override//不管
    public Object getGroup(int groupPosition) {
        return null;
    }

    @Override//不管
    public Object getChild(int groupPosition, int childPosition) {
        return null;
    }

    @Override//不管
    public long getGroupId(int groupPosition) {
        return 0;
    }

    @Override//不管
    public long getChildId(int groupPosition, int childPosition) {
        return 0;
    }
}

效果如下
购物车练习

相关文章: