安卓开发电商mvp框架和流式布局,搜索框

假如想象 提交于 2019-12-24 10:19:23

在这里插入图片描述
在我看来mvp框架其实是mvc框架变种产品。讲原本的activity/fragment的层次划分成present层和view层。m还是原来的实体层用来组装数据,p层则用来隔离view层,被称为中介层,v层还是view层主要用来展示数据的层。如下图所示:

有了present层之后呢?view层就专心在activity/fragment里面主要去处理视图层和维护自己的生命周期,将业务逻辑委托给present层,present层作为实体层和视图层的中介。实体层和视图层不直接进行交互,而是通过委托给persent层进行交互,这样做的好处是:

分离了视图逻辑和业务逻辑,降低了耦合
Activity只处理生命周期的任务,代码变得更加简洁
视图逻辑和业务逻辑分别抽象到了View和Presenter的接口中去,提高代码的可阅读性
Presenter被抽象成接口,可以有多种具体的实现,所以方便进行单元测试
把业务逻辑抽到Presenter中去,避免后台线程引用着Activity导致Activity的资源无法被系统回收从而引起内存泄露和OOM
方便代码的维护和单元测试。

在这里插入图片描述

以下主要展示的功能和框架有:

  1. MVP架构+基类+Volley封装
  2. 底部标签与Fragment的联动
  3. arguments动态传值
  4. 接口回调
  5. js交互,有参无参调用,弹框
  6. 自定义全局异常捕获
  7. base封装Activity和Fragment

第一步:添加需要的依赖和权限创建App上下文管理类,创建全局异常捕获类

在build.gradle下加依赖

 implementation 'com.google.code.gson:gson:2.8.5'
    //volley请求框架
    implementation 'com.android.volley:volley:1.1.1'

    //recycelrview,列表控件,和listview差不多,升级版
    implementation 'androidx.recyclerview:recyclerview:1.1.0'


//glidee
    implementation("com.github.bumptech.glide:glide:4.10.0") {
        exclude group: "com.android.support"
    }

在清单文件加联网权限

<uses-permission android:name="android.permission.INTERNET" />

App

public class App extends Application {


    private static Context context;
    @Override
    public void onCreate() {
        super.onCreate();

        //设置全局异常类,先创建在设置
        final MyCanshHandle myCanshHandle = new MyCanshHandle();

        Thread.setDefaultUncaughtExceptionHandler(myCanshHandle);
        context=getApplicationContext();
    }

    public static Context getContext() {
        return context;
    }
}

全局异常捕获类MyCanshHandle

public class MyCanshHandle implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {

        Log.e("xx",throwable.getMessage());
    }
}

第二步:base封装mvp框架 创建Entity类

Entity类

FlowEntity

public class FlowEntity {


    /**
     * msg : 响应成功
     * code : 200
     * tags : ["手机壁纸","手机app","手机cpu天梯图","手机号码测吉凶","手机新浪网","手机号码测吉凶(超准)","手机电影","手机在线","手机排名","小米手机"]
     */

    private String msg;
    private int code;
    private List<String> tags;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public List<String> getTags() {
        return tags;
    }

    public void setTags(List<String> tags) {
        this.tags = tags;
    }

ProductEntivity

public class ProductEntivity {


    /**
     * result : [{"commodityId":172,"commodityName":"艾奔AspenSpor新款大容量男士双肩包学生书包防盗电脑包充电旅行背包 黑色_标准版","masterPic":"http://172.17.8.100/images/small/commodity/xbsd/dnb/3/1.jpg","price":89,"saleNum":0},{"commodityId":188,"commodityName":"赫登尔(herder)双肩包男时尚旅行背包学生书包电脑包大容量潮流男包0902A","masterPic":"http://172.17.8.100/images/small/commodity/xbsd/sjb/5/1.jpg","price":169,"saleNum":0},{"commodityId":118,"commodityName":" 新款 iPad 128G WIFI 版 平板电脑","masterPic":"http://172.17.8.100/images/small/commodity/sjsm/yyyl/5/1.jpg","price":2988,"saleNum":0},{"commodityId":184,"commodityName":"瑞士军刀双肩包男士背包新款大容量休闲商务旅行电脑包学生书包 USb充电包","masterPic":"http://172.17.8.100/images/small/commodity/xbsd/sjb/1/1.jpg","price":99,"saleNum":0},{"commodityId":174,"commodityName":"帆布派 Canvas artisan 苹果笔记本电脑包 女14/15.6寸惠普电脑包联想1 PT38-1酒红色 14寸可用","masterPic":"http://172.17.8.100/images/small/commodity/xbsd/dnb/5/1.jpg","price":229,"saleNum":0}]
     * message : 查询成功
     * status : 0000
     */

    private String message;
    private String status;
    private List<ResultBean> result;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public List<ResultBean> getResult() {
        return result;
    }

    public void setResult(List<ResultBean> result) {
        this.result = result;
    }

    public static class ResultBean {
        /**
         * commodityId : 172
         * commodityName : 艾奔AspenSpor新款大容量男士双肩包学生书包防盗电脑包充电旅行背包 黑色_标准版
         * masterPic : http://172.17.8.100/images/small/commodity/xbsd/dnb/3/1.jpg
         * price : 89
         * saleNum : 0
         */

        private int commodityId;
        private String commodityName;
        private String masterPic;
        private int price;
        private int saleNum;

        public int getCommodityId() {
            return commodityId;
        }

        public void setCommodityId(int commodityId) {
            this.commodityId = commodityId;
        }

        public String getCommodityName() {
            return commodityName;
        }

        public void setCommodityName(String commodityName) {
            this.commodityName = commodityName;
        }

        public String getMasterPic() {
            return masterPic;
        }

        public void setMasterPic(String masterPic) {
            this.masterPic = masterPic;
        }

        public int getPrice() {
            return price;
        }

        public void setPrice(int price) {
            this.price = price;
        }

        public int getSaleNum() {
            return saleNum;
        }

        public void setSaleNum(int saleNum) {
            this.saleNum = saleNum;
        }
    }
}

m层:
暂时没用到所以只创建一个接口即可

public interface IBaseModel {
}

v层
也暂时没用到所以只创建一个接口即可

public interface IBaseView {
}

p层

public abstract class BasePresenter<M extends IBaseModel,V extends IBaseView> {

    public M model;
    public WeakReference<V> weakReference;


    public BasePresenter(){
        model=initModel();
    }

    //绑定view
    public void attch(V v){
        weakReference=new WeakReference<>(v);
    }

    protected abstract M initModel();


    //解绑view,解决内存泄露
    public void deach(){
        if (weakReference!=null){
            weakReference.clear();
            weakReference=null;
        }

    }

    public V getview(){
        return weakReference.get();
    }
}

第三步:封装BaseActivity和BaseFragment类

BaseActivity

public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements IBaseView {

    public P presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(layoutId());

        presenter=initPresenter();


        //绑定view
        if (presenter!=null){
            presenter.attch(this);
        }

        initView();

        initData();

    }


    //让子类创建
    protected abstract P initPresenter();

    protected abstract void initData();

    protected abstract void initView();

    protected abstract int layoutId();


    //解决内存泄漏
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (presenter!=null) {
            presenter.deach();
        }
    }
}

BaseFragment

public abstract class BaseFragment<P extends BasePresenter> extends Fragment implements IBaseView {

    public P presenter;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        final View inflate = View.inflate(getActivity(), layoutId(), null);

        presenter=initPresenter();

        //绑定view
        if (presenter!=null){
            presenter.attch(this);
        }

        initView(inflate);

        return inflate;

    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initData();
    }

    protected abstract void initData();

    protected abstract void initView(View inflate);

    protected abstract P initPresenter();

    protected abstract int layoutId();


    //解决内存泄漏
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (presenter!=null){
            presenter.deach();
        }
    }
}

第四部,单例模式封装网络工具类Volley,mvp分包,创建统一契约类管理

网络工具类VolleyUtlis

public class VolleyUtlis {

    private RequestQueue requestQueue;//volley请求队列

    private static VolleyUtlis volleyUtlis;
    //双重检验锁的单例模式---企业中,让你手写单例模式


    //暴露公共方法,创建私有对象,供外部调用,双重:两次判断,检验锁:同步锁
    public static VolleyUtlis getInstance() {
        if (volleyUtlis==null){
            synchronized (Volley.class){
                volleyUtlis=new VolleyUtlis();
            }
        }
        return volleyUtlis;
    }

    //构造方法私有,防止外界(调用者)new 出新的对象
    private VolleyUtlis(){
        requestQueue=Volley.newRequestQueue(App.getContext());
    }


    public void doGet(String url, final VolleyCallBack volleyCallBack){

        final StringRequest stringRequest = new StringRequest(StringRequest.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                volleyCallBack.success(response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                volleyCallBack.error(error);
            }
        });

        requestQueue.add(stringRequest);
    }

    public interface VolleyCallBack{
        void success(String json);
        void error(Throwable throwable);
    }
}

契约类ShouyeContract

public interface ShouyeContract{

    interface IModel extends IBaseModel {
        void getFlow(String url,ImodelCallBack imodelCallBack);
        void getProduct(String url,ImodelCallBack imodelCallBack);
        interface ImodelCallBack{
            void success(Object data);
            void error(Throwable throwable);
        }
    }

    interface IView extends IBaseView {
        void success(Object data);
        void error(Throwable throwable);
    }

    interface IPresenter{
        void getFlow(String url);
        void getProduct(String url);
    }
}

M层 ShouyeModel

public class ShouyeModel implements ShouyeContract.IModel {
    @Override
    public void getFlow(String url, final ImodelCallBack imodelCallBack) {
        VolleyUtlis.getInstance().doGet(url, new VolleyUtlis.VolleyCallBack() {
            @Override
            public void success(String json) {
                final FlowEntity flowEntity = new Gson().fromJson(json, FlowEntity.class);

                imodelCallBack.success(flowEntity);
            }

            @Override
            public void error(Throwable throwable) {
                imodelCallBack.error(throwable);
            }
        });
    }

    @Override
    public void getProduct(String url, final ImodelCallBack imodelCallBack) {

        VolleyUtlis.getInstance().doGet(url, new VolleyUtlis.VolleyCallBack() {
            @Override
            public void success(String json) {
                final ProductEntivity productEntivity = new Gson().fromJson(json, ProductEntivity.class);

                imodelCallBack.success(productEntivity);
            }

            @Override
            public void error(Throwable throwable) {

                imodelCallBack.error(throwable);
            }
        });
    }
}

v层可以不写,因为activivty,adapter,有关数据的都可以在v层

p层

public class ShouyePresenter extends BasePresenter<ShouyeModel, ShouyeContract.IView> implements ShouyeContract.IPresenter {
    @Override
    public void getFlow(String url) {
        model.getFlow(url, new ShouyeContract.IModel.ImodelCallBack() {
            @Override
            public void success(Object data) {
                getview().success(data);
            }

            @Override
            public void error(Throwable throwable) {

                getview().error(throwable);
            }
        });
    }

    @Override
    public void getProduct(String url) {
        model.getProduct(url, new ShouyeContract.IModel.ImodelCallBack() {
            @Override
            public void success(Object data) {
                getview().success(data);
            }

            @Override
            public void error(Throwable throwable) {
                getview().error(throwable);
            }
        });
    }

    @Override
    protected ShouyeModel initModel() {
        return new ShouyeModel();
    }
}

第五步底部导航 加动态传值setArguments

布局xml

<?xml version="1.0" encoding="utf-8"?>
<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:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".view.activity.MainActivity">


    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <RadioGroup

        android:id="@+id/rg"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <RadioButton
            android:padding="10dp"
            android:text="首页"
            android:gravity="center"
            android:id="@+id/r1"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:background="@drawable/select"
            android:button="@null"
            android:layout_height="wrap_content"/>
        <RadioButton
            android:padding="10dp"
            android:gravity="center"
            android:text="新闻"
            android:button="@null"
            android:id="@+id/r2"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:background="@drawable/select"
            android:layout_height="wrap_content"/>
        <RadioButton
            android:padding="10dp"
            android:button="@null"
            android:gravity="center"
            android:text="我的"
            android:id="@+id/r3"
            android:layout_weight="1"
            android:background="@drawable/select"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
    </RadioGroup>
</LinearLayout>

然后创建两个fragment

一个首页fragment,一个共用fragment

activity

public class MainActivity extends BaseActivity {



    private ViewPager vp;
    private RadioGroup rg;


    @Override
    protected void initData() {
        final List<Fragment> list=new ArrayList<>();


        final ShouyeFragment shouyeFragment = new ShouyeFragment();
        list.add(shouyeFragment);

        final OtherFragment otherFragment = new OtherFragment();
        //setArguments传值
        final Bundle bundle = new Bundle();
        bundle.putString("name","新闻");
        otherFragment.setArguments(bundle);
        list.add(otherFragment);

        //setArguments传值
        final OtherFragment otherFragment1 = new OtherFragment();
        final Bundle bundle1 = new Bundle();
        bundle1.putString("name","我的");
        otherFragment1.setArguments(bundle1);
        list.add(otherFragment1);

        rg.check(rg.getChildAt(0).getId());

        vp.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @NonNull
            @Override
            public Fragment getItem(int position) {
                return list.get(position);
            }

            @Override
            public int getCount() {
                return list.size();
            }
        });

        vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                rg.check(rg.getChildAt(position).getId());
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });


        rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int i) {
                switch (i){
                    case R.id.r1:
                        vp.setCurrentItem(0);
                        break;
                    case R.id.r2:
                        vp.setCurrentItem(1);
                        break;
                    case R.id.r3:
                        vp.setCurrentItem(2);
                        break;
                }
            }
        });
    }

    @Override
    protected void initView() {
        vp = findViewById(R.id.vp);
        rg = findViewById(R.id.rg);
    }

    @Override
    protected BasePresenter initPresenter() {
        return null;
    }

    @Override
    protected int layoutId() {
        return R.layout.activity_main;
    }
}

OtherFragment
接收传值并设置

public class OtherFragment extends Fragment {

    private TextView tt;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        final View
                inflate = View.inflate(getContext(), R.layout.fragment_other, null);

        final TextView tt = inflate.findViewById(R.id.tt);


        //接收setarguments传来的值
        final Bundle arguments = getArguments();

        final String name = arguments.getString("name");

        tt.setText(name);
        return inflate;
    }
}

布局
fragment_other.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".view.fragment.OtherFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:id="@+id/tt"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />

</FrameLayout>

第六部自定义view显示流式布局和拓展功能,点击搜索框显示相对应的RecyclerView列表,点击列表

FlowLayout

public class FlowLayout extends ViewGroup {
    public FlowLayout(Context context) {
        super(context);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {

        int left=0;
        int top=0;
        int right=0;
        int bottom=0;

        //得到子控件的数量
        final int childCount = getChildCount();

        if (childCount>0){
            //循环每一个子控件
            for (int j = 0; j < childCount; j++) {
                final View childAt = getChildAt(j);

                //子view添加进去的,所以要让系统测量一下每个子控件的大小
                childAt.measure(0,0);

                final int measuredWidth = childAt.getMeasuredWidth();//view的宽
                final int measuredHeight = childAt.getMeasuredHeight();//view的高

                //屏幕宽度,px像素单位
                final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
                final int widthPixels = displayMetrics.widthPixels;

                //累加right
                right=left+measuredWidth;
                if (right>widthPixels){
                    //折行后第一个控件距离左边距离为0
                    left=0;
                    right=left+measuredWidth;
                    top=bottom+30;
                }

                bottom=top+measuredHeight;

                //就是对view进行摆放
                childAt.layout(left,top,right,bottom);

                left=left+measuredWidth+30;
            }
        }
    }


    //显示流式布局,加入数据
    public void add(List<String> tags){
        for (String tag : tags) {

            //动态创建textview
            final TextView textView = new TextView(getContext());

            //设置文本
            textView.setText(tag);

            //添加子控件到流式布局中
            addView(textView);
        }
    }

    //将输入的数据单个添加到流式布局中
    public void addTextView(String name){

        final TextView textView = new TextView(getContext());

        textView.setText(name);

        addView(textView);

        //最后,设置回调接口准备过去的数据
        textView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                flowonClickListenter.onClick(textView.getText().toString());
            }
        });

    }


    //第二步,声明接口
    private FlowonClickListenter flowonClickListenter;

    //第三部
    public void setFlowonClickListenter(FlowonClickListenter flowonClickListenter) {
        this.flowonClickListenter = flowonClickListenter;
    }


    //第一步创建回调接口
    public interface FlowonClickListenter{
        void onClick(String name);
    }

}

然后在首页fragment显示

public class ShouyeFragment extends BaseFragment<ShouyePresenter> implements ShouyeContract.IView {


    private FlowLayout flow_layout;
    private Button btn_search;
    private EditText et_keyword;
    private RecyclerView rv;

    @Override
    protected void initData() {

        String url = "http://blog.zhaoliang5156.cn/baweiapi/"+ URLEncoder.encode("手机");
        presenter.getFlow(url);
    }

    @Override
    protected void initView(View inflate) {

        flow_layout = inflate.findViewById(R.id.flow_layout);

        btn_search = inflate.findViewById(R.id.btn_search);
        et_keyword = inflate.findViewById(R.id.et_keyword);
        rv = inflate.findViewById(R.id.rv);


        rv.setLayoutManager(new GridLayoutManager(getActivity(),2));



        flow_layout.setFlowonClickListenter(new FlowLayout.FlowonClickListenter() {
            @Override
            public void onClick(String name) {
                String url = "http://172.17.8.100/small/commodity/v1/findCommodityByKeyword?keyword="+URLEncoder.encode(name)+"&count=10&page=1";

                presenter.getProduct(url);
            }
        });


        btn_search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                flow_layout.addTextView(et_keyword.getText().toString());

                String url = "http://172.17.8.100/small/commodity/v1/findCommodityByKeyword?keyword="+URLEncoder.encode(et_keyword.getText().toString())+"&count=10&page=1";

                presenter.getProduct(url);
            }
        });


    }

    @Override
    protected ShouyePresenter initPresenter() {
        return new ShouyePresenter();
    }

    @Override
    protected int layoutId() {
        return R.layout.fragment_shouye;
    }

    @Override
    public void success(Object data) {
        if (data instanceof FlowEntity){
            final List<String> tags = ((FlowEntity) data).getTags();

            flow_layout.add(tags);
        }else if (data instanceof ProductEntivity){

            final List<ProductEntivity.ResultBean> result = ((ProductEntivity) data).getResult();

            final ProductAdapter productAdapter = new ProductAdapter(getActivity(), result);

            rv.setAdapter(productAdapter);

            productAdapter.setRvItemlistenter(new ProductAdapter.RvItemlistenter() {
                @Override
                public void onclick(String name) {
                    Toast.makeText(getContext(), ""+name, Toast.LENGTH_SHORT).show();
                    final Intent intent = new Intent(getContext(), SecondActivity.class);

                    startActivity(intent);

                }
            });
        }
    }

    @Override
    public void error(Throwable throwable) {

    }
}

布局
fragment_shouye.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".view.fragment.ShouyeFragment">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" android:orientation="horizontal">
        <EditText
            android:id="@+id/et_keyword"
            android:hint="请输入搜索关键词"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <Button
            android:id="@+id/btn_search"
            android:text="搜索"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>


    </LinearLayout>

    <com.bawei.yuekao.view.widgets.FlowLayout
        android:id="@+id/flow_layout"
        android:layout_width="match_parent"
        android:layout_height="300dp">

    </com.bawei.yuekao.view.widgets.FlowLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </androidx.recyclerview.widget.RecyclerView>

</LinearLayout>

RecyclerView适配器

public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.MyViewHorlder> {


    private Context context;

    private List<ProductEntivity.ResultBean> list;

    public ProductAdapter(Context context, List<ProductEntivity.ResultBean> list) {
        this.context = context;
        this.list = list;
    }

    @NonNull
    @Override
    public MyViewHorlder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        final View inflate = View.inflate(context, R.layout.product_item_layout, null);

        final MyViewHorlder myViewHorlder = new MyViewHorlder(inflate);


        return myViewHorlder;
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHorlder holder, final int position) {
        holder.name.setText(list.get(position).getCommodityName());

        Glide.with(context)
                .load(list.get(position).getMasterPic())
                .placeholder(R.mipmap.ic_launcher)
                .error(R.mipmap.ic_launcher)
                .circleCrop()
                .into(holder.iv);



        //点击事件,通过下面声明的接口,发送商品标题
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                rvItemlistenter.onclick(list.get(position).getCommodityName());
            }
        });

    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    class MyViewHorlder extends RecyclerView.ViewHolder {

        private final ImageView iv;
        private final TextView name;

        public MyViewHorlder(@NonNull View itemView) {
            super(itemView);

            iv = itemView.findViewById(R.id.iv);
            name = itemView.findViewById(R.id.name);
        }
    }


    private RvItemlistenter rvItemlistenter;

    public void setRvItemlistenter(RvItemlistenter rvItemlistenter) {
        this.rvItemlistenter = rvItemlistenter;
    }

    public interface RvItemlistenter{
        void onclick(String name);
    }

}

布局
product_item_layout.xml

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

    <ImageView
        android:id="@+id/iv"
        android:layout_width="80dp"
        android:layout_height="80dp"/>

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

第7步 js交互,有参无参调用,弹框

在main里创建一个assets包
创建一个html

<html>


<head>

    <meta charset="UTF-8">

    <script type="text/javascript">

        function dhx(zhy){

        document.getElementsByClassName("name").innerHTML=zhy;

        alert(zhy);
        }

    </script>
</head>



<body>

<p>

</p>

<p>我是一个段落</p>
<p class="name">我是从Android过来</p>
<button onclick="window.aaa.getZhy('电脑')">有参调用android</button>
<button onclick="window.aaa.getDhx()">无参调用android</button>

</body>
</html>

activity

随便创建一个类交互

public class Zhy {

    @JavascriptInterface//必须写
    public void getZhy(String name){
        Toast.makeText(App.getContext(), ""+name, Toast.LENGTH_SHORT).show();
    }

    @JavascriptInterface
    public void getDhx(){
        Toast.makeText(App.getContext(), "这是无参", Toast.LENGTH_SHORT).show();
    }
}

SecondActivity 实现功能

public class SecondActivity extends BaseActivity {


    private Button b1;
    private WebView web;

    @Override
    protected BasePresenter initPresenter() {
        return null;
    }

    @Override
    protected void initData() {

    }

    @Override
    protected void initView() {
        b1 = findViewById(R.id.b1);
        web = findViewById(R.id.web);

        web.getSettings().setJavaScriptEnabled(true);
        web.setWebChromeClient(new WebChromeClient());

        final Zhy zhy = new Zhy();

        web.addJavascriptInterface(zhy,"aaa");

        web.loadUrl("file:///android_asset/hello.html");


        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {



                web.loadUrl("javascript:dhx()");
            }
        });
    }

    @Override
    protected int layoutId() {
        return R.layout.activity_second;
    }
}

布局
activity_second.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_height="match_parent"
    tools:context=".view.activity.SecondActivity">


    <WebView
        android:id="@+id/web"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </WebView>

    <Button
        android:id="@+id/b1"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:text="去调用js的空参"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

    </Button>

</RelativeLayout>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!