//可能需要的依赖
//配置retrofit2.0
implementation 'com.squareup.retrofit2:retrofit:+'
implementation 'com.squareup.retrofit2:converter-gson:+'
//Rxjava2需要依赖
implementation 'io.reactivex.rxjava2:rxjava:+'
implementation 'io.reactivex.rxjava2:rxandroid:+'
//让retrofit支持Rxjava2
implementation 'com.squareup.retrofit2:adapter-rxjava2:+'
//reclerview的依赖
implementation 'com.android.support:recyclerview-v7:27.1.1'
//xRecyclerView的依赖
implementation 'com.jcodecraeer:xrecyclerview:1.3.2'
implementation 'com.android.support:design:27.1.1'
//fresco依赖
implementation 'com.facebook.fresco:fresco:1.9.0'
//banner轮播图
implementation 'com.youth.banner:banner:1.4.10'
//1.1.0 API改动过大,老用户升级需谨慎
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-11'
implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.1.0-alpha-11'
//没有使用特殊Header,可以不加这行
implementation project(':libzxing')
//拦截器的依赖
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
//butterknife插件依赖
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
//跑马灯
implementation 'com.sunfusheng:marqueeview:1.3.3'
//Glide 加载图片
implementation 'com.github.bumptech.glide:glide:4.7.1'
implementation 'org.greenrobot:eventbus:3.0.0'
//RetroFitManager工具类
package com.bw.my_jingdong.utils; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; /** * retrofit工具类 */ public class RetrofitManager { private static final String BAS_URL =HttpConfig.BASE_URL; private Retrofit retrofit; private static class SingleHolder { private static final RetrofitManager INSTANCE = new RetrofitManager(BAS_URL); } public static RetrofitManager getDefault() { return SingleHolder.INSTANCE; } public RetrofitManager(String basUrl) { retrofit = new Retrofit.Builder() .baseUrl(basUrl) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(buildOkHttpClient()) .build(); } private OkHttpClient buildOkHttpClient() { //拦截器 HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); return new OkHttpClient.Builder() .readTimeout(5000, TimeUnit.SECONDS) .addInterceptor(httpLoggingInterceptor) .build(); } public <T> T create(Class<T> clazz) { return retrofit.create(clazz); } }
//接口类
public static final String BASE_URL = "https://www.zhaoapi.cn/";
//查询购物车 public static final String JD_SHOPPING_CART = "product/getCarts"; //添加购物车 public static final String JD_ADD_CART="product/addCart";
//Api类
import com.bw.my_jingdong.mvp.cart.model.bean.AddRessBean; import com.bw.my_jingdong.mvp.cart.model.bean.CartBean; import com.bw.my_jingdong.mvp.cart.model.bean.CartRemoveBean; import com.bw.my_jingdong.mvp.cart.model.bean.CreateOrderBean; import com.bw.my_jingdong.mvp.cart.model.bean.DefaultAddrBean; import com.bw.my_jingdong.mvp.cart.model.bean.GetAddrBean; import com.bw.my_jingdong.mvp.cart.model.bean.QueryAddrBean; import com.bw.my_jingdong.mvp.cart.model.bean.QueryOrderBean; import com.bw.my_jingdong.mvp.cart.model.bean.UpdateAddrBean; import com.bw.my_jingdong.mvp.cart.model.bean.UpdateOrderBean; import com.bw.my_jingdong.mvp.classes.model.bean.ClassesBeanLeft; import com.bw.my_jingdong.utils.HttpConfig; import io.reactivex.Observable; import retrofit2.http.GET; import retrofit2.http.Query; public interface ICartApi { //查询购物车 @GET(HttpConfig.JD_SHOPPING_CART) Observable<CartBean> doCart(@Query("uid") int uid); //删除购物车 商品 @GET(HttpConfig.JD_CART_REMOVE_GOODS) Observable<CartRemoveBean> doRemoveCart(@Query("uid") int uid, @Query("pid") int pid); }
//model层
//查询购物车 public Observable<CartBean> doCart(int uid){ return RetrofitManager.getDefault().create(ICartApi.class).doCart(uid); } //删除购物车 public Observable<CartRemoveBean> doRemoveGoods(int uid,int pid){ return RetrofitManager.getDefault().create(ICartApi.class).doRemoveCart(uid,pid); }
//presenter
package com.bw.my_jingdong.mvp.cart.presenter; import android.util.Log; import com.bw.my_jingdong.base.BasePresenter; import com.bw.my_jingdong.mvp.cart.model.cartmodel.CartModel; import com.bw.my_jingdong.mvp.cart.model.bean.CartBean; import com.bw.my_jingdong.mvp.cart.model.bean.CartRemoveBean; import com.bw.my_jingdong.mvp.cart.model.bean.CreateOrderBean; import com.bw.my_jingdong.mvp.cart.view.view.CartView; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; public class CartPresenter extends BasePresenter<CartView> { private CartModel cartModel; public CartPresenter(CartView view) { super(view); } @Override protected void initModel() { cartModel = new CartModel(); } //查询购物车 public void getCart(int uid) { cartModel.doCart(uid) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<CartBean>() { @Override public void onSubscribe(Disposable d) { compositeDisposable.add(d); } @Override public void onNext(CartBean cartBean) { Log.e("tag", "onNext: " + cartBean.getMsg()); if (view != null) { view.onSuccess(cartBean); } } @Override public void onError(Throwable e) { if (view != null) { view.onFaild(e.toString()); } } @Override public void onComplete() { } }); } //删除购物车商品 public void removeCartGoods(int uid, int pid) { cartModel.doRemoveGoods(uid, pid) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<CartRemoveBean>() { @Override public void onSubscribe(Disposable d) { compositeDisposable.add(d); } @Override public void onNext(CartRemoveBean cartRemoveBean) { String code = cartRemoveBean.getCode(); if ("0".equals(code)) { if (view != null) { view.onRemoveSuccess(cartRemoveBean); } } else { if (view != null) { view.onRemoveFaild("访问错误"); } } } @Override public void onError(Throwable e) { if (view != null) { view.onRemoveFaild(e.toString()); } } @Override public void onComplete() { } }); } }
//View层
package com.bw.my_jingdong.mvp.cart.view.view; import com.bw.my_jingdong.base.IView; import com.bw.my_jingdong.mvp.cart.model.bean.CartBean; import com.bw.my_jingdong.mvp.cart.model.bean.CartRemoveBean; import com.bw.my_jingdong.mvp.cart.model.bean.CreateOrderBean; public interface CartView extends IView { void onSuccess(CartBean cartBean); void onFaild(String error); void onRemoveSuccess(CartRemoveBean cartRemoveBean); void onRemoveFaild(String error); void onCreateOderSuccess(CreateOrderBean createOrderBean); void onCreateFaild(String error); }
//主页面布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ExpandableListView android:id="@+id/cart_expand" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="50dp"></ExpandableListView> <LinearLayout android:layout_width="match_parent" android:layout_height="60sp" android:layout_alignParentBottom="true"> <CheckBox android:id="@+id/quanxuan" 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/he" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_weight="1" android:text="合计:¥0.0" /> <Button android:id="@+id/btn_buy" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="总数量" /> <Button android:id="@+id/cart_create_order" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="去结算" /> </LinearLayout> </RelativeLayout>
//购物车适配器布局
<?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="60sp" android:layout_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" android:text="文字" /> </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:layout_gravity="center_vertical" > <CheckBox android:id="@+id/child_cb" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/productImg" android:layout_width="70dp" android:layout_height="70dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/product_title_name_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="商品标题" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/child_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥0.0" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <com.bw.my_jingdong.mvp.cart.view.activity.MyAddSub android:id="@+id/my_sub_add" android:layout_width="wrap_content" android:layout_height="wrap_content" > </com.bw.my_jingdong.mvp.cart.view.activity.MyAddSub> <Button android:id="@+id/cart_child_remove" android:layout_width="70dp" android:layout_height="50dp" android:text="删除" /> </LinearLayout> </LinearLayout> </LinearLayout>
//适配器
package com.bw.my_jingdong.mvp.cart.view.adapter; import android.net.Uri; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; import android.widget.Toast; import com.bw.my_jingdong.R; import com.bw.my_jingdong.mvp.cart.model.bean.CartBean; import com.bw.my_jingdong.mvp.cart.view.activity.MyAddSub; import com.facebook.drawee.view.SimpleDraweeView; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; public class ExpandViewAdapter extends BaseExpandableListAdapter { private List<CartBean.DataBean> seller; private static final String TAG = "适配器********"; public ExpandViewAdapter(List<CartBean.DataBean> seller) { this.seller = seller; } @Override public int getGroupCount() { return seller == null ? 0 : seller.size(); } @Override public int getChildrenCount(int groupPosition) { return seller.get(groupPosition).getList().size(); } @Override public Object getGroup(int groupPosition) { return seller.get(groupPosition); } @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; } @Override public boolean hasStableIds() { return false; } @Override public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { CartBean.DataBean dataBean = seller.get(groupPosition); ParentHolder parentHolder; if (convertView == null) { convertView = View.inflate(parent.getContext(), R.layout.cart_parent, null); parentHolder = new ParentHolder(convertView); convertView.setTag(parentHolder); } else { parentHolder = (ParentHolder) convertView.getTag(); } //赋值商家名称 parentHolder.sellerNameTv.setText(dataBean.getSellerName()); boolean b = productStatus(groupPosition); parentHolder.sellerCb.setChecked(b); parentHolder.sellerCb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (onCartListChangeListener != null) { onCartListChangeListener.SellerCheckChange(groupPosition); } } }); return convertView; } @Override public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, final ViewGroup parent) { CartBean.DataBean.ListBean listBean = seller.get(groupPosition).getList().get(childPosition); ChildHolder childHolder; if (convertView == null) { convertView = View.inflate(parent.getContext(), R.layout.cart_child, null); childHolder = new ChildHolder(convertView); convertView.setTag(childHolder); } else { childHolder = (ChildHolder) convertView.getTag(); } //赋值子类名称 childHolder.productTitleNameTv.setText(listBean.getTitle()); childHolder.childPrice.setText(listBean.getBargainPrice() + ""); String[] pic = listBean.getImages().split("\\|"); Uri uri = Uri.parse(pic[0]); childHolder.productImg.setImageURI(uri); boolean flag = listBean.getSelected() == 1 ? true : false; childHolder.childCb.setChecked(flag); childHolder.childCb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (onCartListChangeListener != null) { onCartListChangeListener.onProductCheckedChange(groupPosition, childPosition); Toast.makeText(parent.getContext(), "kkkkk", Toast.LENGTH_SHORT).show(); } } }); childHolder.mySubAdd.setNumber(listBean.getNum()); childHolder.mySubAdd.setOnNumberChangeListener(new MyAddSub.onNumberChangeListener() { @Override public void onAddNumberChange(int product_num) { if (onCartListChangeListener != null) { onCartListChangeListener.onProductNumberChange(groupPosition, childPosition, product_num); } } @Override public void onSubNumberChange(int product_num) { if (onCartListChangeListener != null) { onCartListChangeListener.onProductNumberChange(groupPosition, childPosition, product_num); } } }); childHolder.cartChildRemove.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (onCartListChangeListener != null) { onCartListChangeListener.onRemoveCartListener(groupPosition, childPosition); } } }); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return false; } //关于商家按钮 public boolean productStatus(int groupPosition) { List<CartBean.DataBean.ListBean> list = seller.get(groupPosition).getList(); for (CartBean.DataBean.ListBean listBean : list) { if (listBean.getSelected() == 0) { return false; } } return true; } //子类按钮跟着改变 public void noProductStatus(int groupPosition, boolean b) { List<CartBean.DataBean.ListBean> list = seller.get(groupPosition).getList(); for (int i = 0; i < list.size(); i++) { list.get(i).setSelected(b ? 1 : 0); } } //判断所有商品是否选中 public boolean isAllProductSelected() { for (int i = 0; i < seller.size(); i++) { List<CartBean.DataBean.ListBean> list = seller.get(i).getList(); for (int j = 0; j < list.size(); j++) { if (list.get(j).getSelected() == 0) { return false; } } } return true; } //关于底部全选按钮 public void changeAllProductStatus(boolean selected) { for (int i = 0; i < seller.size(); i++) { List<CartBean.DataBean.ListBean> list = seller.get(i).getList(); for (int j = 0; j < list.size(); j++) { list.get(j).setSelected(selected ? 1 : 0); } } } //关于子类按钮 public void changeCurrentProductStatus(int groupPosition, int childPosition) { List<CartBean.DataBean.ListBean> list = seller.get(groupPosition).getList(); CartBean.DataBean.ListBean listBean = list.get(childPosition); listBean.setSelected(listBean.getSelected() == 0 ? 1 : 0); } //总价格 public float calcuteTotalPrice() { float totlaPrice = 0; for (int i = 0; i < seller.size(); i++) { List<CartBean.DataBean.ListBean> list = seller.get(i).getList(); for (int j = 0; j < list.size(); j++) { if (list.get(j).getSelected() == 1) { float price = list.get(j).getBargainPrice(); int num = list.get(j).getNum(); totlaPrice += num * price; } } } return totlaPrice; } //总数量 public int cacuteTotalNum() { int totalNum = 0; for (int i = 0; i < seller.size(); i++) { List<CartBean.DataBean.ListBean> list = seller.get(i).getList(); for (int j = 0; j < list.size(); j++) { if (list.get(j).getSelected() == 1) { int num = list.get(j).getNum(); totalNum += num; } } } return totalNum; } //设置加减按钮 public void changeCurrentNumberProduct(int groupPosition, int childPosition, int number) { List<CartBean.DataBean.ListBean> list = seller.get(groupPosition).getList(); CartBean.DataBean.ListBean listBean = list.get(childPosition); listBean.setNum(number); } //父类 static class ParentHolder { @BindView(R.id.seller_cb) CheckBox sellerCb; @BindView(R.id.seller_name_tv) TextView sellerNameTv; ParentHolder(View view) { ButterKnife.bind(this, view); } } //子类 onCartListChangeListener onCartListChangeListener; public void setOnCartListChangeListener(ExpandViewAdapter.onCartListChangeListener onCartListChangeListener) { this.onCartListChangeListener = onCartListChangeListener; } //接口回调 public interface onCartListChangeListener { void SellerCheckChange(int groupPosition); void onProductCheckedChange(int groupPosition, int childPosition); void onProductNumberChange(int groupPosition, int childPosition, int number); void onRemoveCartListener(int groupPosition, int childPosition); } static class ChildHolder { @BindView(R.id.child_cb) CheckBox childCb; @BindView(R.id.productImg) SimpleDraweeView productImg; @BindView(R.id.product_title_name_tv) TextView productTitleNameTv; @BindView(R.id.child_price) TextView childPrice; @BindView(R.id.my_sub_add) MyAddSub mySubAdd; @BindView(R.id.cart_child_remove) Button cartChildRemove; ChildHolder(View view) { ButterKnife.bind(this, view); } } }
//购物车主页面
package com.bw.my_jingdong.mvp.cart.view.fragment; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.ExpandableListView; import android.widget.TextView; import android.widget.Toast; import com.bw.my_jingdong.R; import com.bw.my_jingdong.base.BaseFragment; import com.bw.my_jingdong.mvp.cart.model.bean.CartBean; import com.bw.my_jingdong.mvp.cart.model.bean.CartRemoveBean; import com.bw.my_jingdong.mvp.cart.model.bean.CreateOrderBean; import com.bw.my_jingdong.mvp.cart.presenter.CartPresenter; import com.bw.my_jingdong.mvp.cart.view.activity.QueryOrderActivity; import com.bw.my_jingdong.mvp.cart.view.adapter.ExpandViewAdapter; import com.bw.my_jingdong.mvp.cart.view.view.CartView; import java.util.List; import static android.content.Context.MODE_PRIVATE; public class CartFragment extends BaseFragment<CartPresenter> implements CartView { private ExpandableListView cart_expand; private CheckBox ck_quanxuan; private TextView tv_he; private Button btn_num; private ExpandViewAdapter adapter; private List<CartBean.DataBean> data; private Button btn_create_order; private float totalPrice; private int uid; //获取id @Override protected void initViews(View view) { cart_expand = view.findViewById(R.id.cart_expand); ck_quanxuan = view.findViewById(R.id.quanxuan); tv_he = view.findViewById(R.id.he); btn_num = view.findViewById(R.id.btn_buy); //去结算 btn_create_order = view.findViewById(R.id.cart_create_order); } @Override protected void initData() { //和登录绑定 SharedPreferences p = getContext().getSharedPreferences("mobile", MODE_PRIVATE); boolean flag = p.getBoolean("flag", false); uid = p.getInt("uid", 0); if (flag) { presenter.getCart(uid); } } @Override protected void initListener() { ck_quanxuan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //底部全选按钮 boolean allProductSelected = adapter.isAllProductSelected(); adapter.changeAllProductStatus(!allProductSelected); //刷新适配器 adapter.notifyDataSetChanged(); reFreshSelectedAndToTalPriceAndTotalAllNumber(); } }); btn_create_order.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (totalPrice < 1) { Toast.makeText(getContext(), "商品未选中", Toast.LENGTH_SHORT).show(); }else{ presenter.CreateOrder(uid,totalPrice); } } }); } @Override protected CartPresenter provide() { return new CartPresenter((CartView) this); } @Override protected int provId() { return R.layout.cartfragment; } //成功 @Override public void onSuccess(CartBean cartBean) { data = cartBean.getData(); //创建适配器 adapter = new ExpandViewAdapter(data); cart_expand.setAdapter(adapter); reFreshSelectedAndToTalPriceAndTotalAllNumber(); adapter.setOnCartListChangeListener(new ExpandViewAdapter.onCartListChangeListener() { @Override public void SellerCheckChange(int groupPosition) { //设置商家 boolean b = adapter.productStatus(groupPosition); //子类按钮跟着改变 adapter.noProductStatus(groupPosition, !b); //刷新适配器 adapter.notifyDataSetChanged(); reFreshSelectedAndToTalPriceAndTotalAllNumber(); } @Override public void onProductCheckedChange(int groupPosition, int childPosition) { adapter.changeCurrentProductStatus(groupPosition, childPosition); //刷新适配器 adapter.notifyDataSetChanged(); reFreshSelectedAndToTalPriceAndTotalAllNumber(); } @Override public void onProductNumberChange(int groupPosition, int childPosition, int number) { //设置加减按钮 adapter.changeCurrentNumberProduct(groupPosition, childPosition, number); //刷新适配器 adapter.notifyDataSetChanged(); reFreshSelectedAndToTalPriceAndTotalAllNumber(); } @Override public void onRemoveCartListener(int groupPosition, int childPosition) { int pid = data.get(groupPosition).getList().get(childPosition).getPid(); SharedPreferences p = getActivity().getSharedPreferences("mobile", MODE_PRIVATE); SharedPreferences.Editor edit = p.edit(); int uid = p.getInt("uid", 0); presenter.removeCartGoods(uid, pid); } }); //展开二级列表 for (int i = 0; i < data.size(); i++) { cart_expand.expandGroup(i); } } @Override public void onFaild(String error) { if (adapter != null) { data.clear(); adapter.notifyDataSetChanged(); } } @Override public void onRemoveSuccess(CartRemoveBean cartRemoveBean) { initData(); //刷新适配器 adapter.notifyDataSetChanged(); reFreshSelectedAndToTalPriceAndTotalAllNumber(); } @Override public void onRemoveFaild(String error) { } //点击创建订单 @Override public void onCreateOderSuccess(CreateOrderBean createOrderBean) { String code = createOrderBean.getCode(); if ("0".equals(code)){ Intent it = new Intent(getContext(), QueryOrderActivity.class); startActivity(it); Toast.makeText(getContext(), "订单创建成功", Toast.LENGTH_SHORT).show(); } } @Override public void onCreateFaild(String error) { } @Override public Context cotext() { return getContext(); } public void reFreshSelectedAndToTalPriceAndTotalAllNumber() { //判断是否全部选中 boolean allProductSelected = adapter.isAllProductSelected(); ck_quanxuan.setChecked(allProductSelected); //设置总价格 totalPrice = adapter.calcuteTotalPrice(); tv_he.setText("总价格(" + totalPrice + ")"); //总数量 int totalNum = adapter.cacuteTotalNum(); btn_num.setText("总数量" + totalNum); } }