MVP框架+RecyclerView展示+点击条目删除

本文介绍了如何使用MVP架构在Android应用中实现RecyclerView展示新闻列表,并详细讲解了各组件如NewsModel、NewsPresenter、NewsView的作用。同时,提到了自定义装饰器MyDecoration以及item_one.xml和item_two.xml布局文件的应用。此外,还涵盖了OkHttpUtils工具类的使用和适配器NewsAdapter的编写,以及项目的依赖和权限设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结构图
在这里插入图片描述
activity_main.xml主布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rlv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.constraint.ConstraintLayout>

MainActivity

package com.bw.zhoukao1;

import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.widget.Toast;

import com.bw.zhoukao1.adapter.NewsAdapter;
import com.bw.zhoukao1.presenter.NewsPresenter;
import com.bw.zhoukao1.view.NewsView;
import com.bw.zhoukao1.widget.MyDecoration;

import org.json.JSONArray;

public class MainActivity extends AppCompatActivity implements NewsView {

    private RecyclerView rlv;
    private NewsPresenter presenter;
    private int page = 1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //找控件
        rlv = findViewById(R.id.rlv);

        //创建布局管理器
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        //设置布局管理器
        rlv.setLayoutManager(linearLayoutManager);

        //这句就是添加我们自定义的分隔线
        rlv.addItemDecoration(new MyDecoration(this, MyDecoration.VERTICAL_LIST));

        //实例p
        presenter = new NewsPresenter(this);
        //内部类使用弱引用管理外部类
        presenter.attachView(this);

        //调用p关联m
        presenter.relecte(page);

        //分页
        //下拉刷新的时候page为1
         presenter.relecte(page);
       // 上拉加载 page++
        presenter.relecte(page);

        /**
         * 继续研究
         * 分页
         * MVP 泛型 向上抽取
         * OK 网络拦截器
         * RecyclerView 添加动画
         */



    }

    @Override
    public void onView(JSONArray datas) {
        //接收数据

        Log.i("xxx", datas.length() + "");


        final NewsAdapter adapter = new NewsAdapter(this, datas);

        rlv.setAdapter(adapter);
        //长按监听
        adapter.setOnRecyclerViewItemLongClickLisenter(new NewsAdapter.OnRecyclerViewItemLongClickLisenter() {
            @RequiresApi(api = Build.VERSION_CODES.KITKAT)
            @Override
            public void onRecyclerViewItemLongClick(int position) {
                //接收数据
                Toast.makeText(MainActivity.this, "长按条目:" + position, Toast.LENGTH_SHORT).show();
                 //删除数据
                adapter.removeItem(position);

            }
        });


    }

    //解决内存泄漏

    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.detachView();
    }
}

model层的NewsModel

package com.bw.zhoukao1.model;

import android.os.Handler;
import android.os.Message;

import com.bw.zhoukao1.utils.OkHttpUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;


public class NewsModel {
    private String url = "http://365jia.cn/news/api3/365jia/news/headline";

    //在外部类中定义接口回调
    public interface OnNewsLisenter {
        void onNews(JSONArray datas);
    }

    private OnNewsLisenter lisenter;

    public void setOnNewsLisenter(OnNewsLisenter lisenter) {
        this.lisenter = lisenter;
    }


    //创建
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case 0:
                    String json = (String) msg.obj;
                    try {
                        JSONObject jsonObject = new JSONObject(json);
                        JSONObject data = jsonObject.getJSONObject("data");
                        JSONArray datas = data.getJSONArray("data");
                        //判空
                        if (lisenter != null) {
                            //回调数据
                            lisenter.onNews(datas);
                        }

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    break;
            }

        }
    };

    //获取网络数据
    public void getNewsData(int page) {

        OkHttpUtils.getInstance().doGet(url + "?page=" + page, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String json = response.body().string();

                //发消息
                Message message = new Message();
                message.what = 0;
                message.obj = json;
                handler.sendMessage(message);

            }
        });


    }
}

presenter层的NewsPresenter

package com.bw.zhoukao1.presenter;

import com.bw.zhoukao1.model.NewsModel;
import com.bw.zhoukao1.view.NewsView;

import org.json.JSONArray;

import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * @Auther: jiangnengbao
 * @Date: 2019/2/18 15:45:09
 * @Description:
 */
public class NewsPresenter<T> {


    private final NewsModel model;
    private final NewsView newsView;
    //声明Reference引用
    private Reference<T> reference;

    //构造方法中实例m和v
    public NewsPresenter(NewsView view) {

        newsView = view;

        model = new NewsModel();

    }
    //用弱引用管理view

    public void attachView(T t) {
        //实例
        reference = new WeakReference<T>(t);
    }

    // p关联m
    public void relecte(int page) {

        model.getNewsData(page);

        //设置监听

        model.setOnNewsLisenter(new NewsModel.OnNewsLisenter() {
            @Override
            public void onNews(JSONArray datas) {
                //接收数据
                newsView.onView(datas);

            }
        });


    }

    //解除弱引用中的view
    public void detachView() {
        if (reference.get() != null) {
            reference.clear();
            reference = null;
        }
    }

}

view层的NewsView

package com.bw.zhoukao1.view;

import org.json.JSONArray;

/**
 * @Auther: jiangnengbao
 * @Date: 2019/2/18 16:27:33
 * @Description:
 */
public interface NewsView {

    void onView(JSONArray datas);
}

utils工具类OkHttpUtils

package com.bw.zhoukao1.utils;

import android.util.Log;

import java.util.Map;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * @Auther: jiangnengbao  单例设计模式封装 懒汉
 * @Date: 2019/2/18 15:48:44
 * @Description:
 */
public class OkHttpUtils {

    //私有的静态的成员变量,只声明不创建
    private static OkHttpUtils okHttpUtils = null;
    //私有的构造方法

    private OkHttpUtils() {

    }

    //返回公共静态的实例方法
    public static OkHttpUtils getInstance() {
        if (okHttpUtils == null) {
            synchronized (OkHttpUtils.class) {

                if (okHttpUtils == null) {
                    okHttpUtils = new OkHttpUtils();
                }
            }
        }


        return okHttpUtils;
    }

    private static OkHttpClient okHttpClient = null;

    //返回ok
    public synchronized static OkHttpClient getOkHttpClient() {

        if (okHttpClient == null) {
            //创建日志拦截器
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    Log.i("xxx", message);
                }
            });
            //设置日志拦截器模式
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            //创建okHttpClient

            okHttpClient = new OkHttpClient.Builder().addInterceptor(loggingInterceptor).build();
        }


        return okHttpClient;


    }

//get请求
    public void doGet(String url, Callback callback) {
        //创建OkHttpClient
        OkHttpClient okHttpClient = getOkHttpClient();
        //创建Request
        Request request = new Request.Builder().url(url).build();

        Call call = okHttpClient.newCall(request);
        //执行异步
        call.enqueue(callback);


    }
//post请求
    public void doPost(String url, Map<String, String> parmars, Callback callback) {
        //创建OkHttpClient
        OkHttpClient okHttpClient = getOkHttpClient();
        //创建builder
        FormBody.Builder builder = new FormBody.Builder();
        //遍历集合
        for (String key : parmars.keySet()) {
            builder.add(key,parmars.get(key));

        }

        //构建FormBody
        FormBody formBody = builder.build();

        //创建Request
        Request request = new Request.Builder().url(url).post(formBody).build();

        Call call = okHttpClient.newCall(request);
        //执行异步
        call.enqueue(callback);


    }

}

widget层的MyDecoration

package com.bw.zhoukao1.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;


public class MyDecoration  extends RecyclerView.ItemDecoration{

    private Context mContext;
    private Drawable mDivider;
    private int mOrientation;
    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    //我们通过获取系统属性中的listDivider来添加,在系统中的AppTheme中设置
    public static final int[] ATRRS  = new int[]{
            android.R.attr.listDivider
    };

    public MyDecoration(Context context, int orientation) {
        this.mContext = context;
        final TypedArray ta = context.obtainStyledAttributes(ATRRS);
        this.mDivider = ta.getDrawable(0);
        ta.recycle();
        setOrientation(orientation);
    }

    //设置屏幕的方向
    public void setOrientation(int orientation){
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST){
            throw new IllegalArgumentException("invalid orientation");        }        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == HORIZONTAL_LIST){
            drawVerticalLine(c, parent, state);
        }else {
            drawHorizontalLine(c, parent, state);
        }
    }

    //画横线, 这里的parent其实是显示在屏幕显示的这部分
    public void drawHorizontalLine(Canvas c, RecyclerView parent, RecyclerView.State state){
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++){
            final View child = parent.getChildAt(i);

            //获得child的布局信息
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
            //Log.d("wnw", left + " " + top + " "+right+"   "+bottom+" "+i);
        }
    }

    //画竖线
    public void drawVerticalLine(Canvas c, RecyclerView parent, RecyclerView.State state){
        int top = parent.getPaddingTop();
        int bottom = parent.getHeight() - parent.getPaddingBottom();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++){
            final View child = parent.getChildAt(i);

            //获得child的布局信息
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    //由于Divider也有长宽高,每一个Item需要向下或者向右偏移
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if(mOrientation == HORIZONTAL_LIST){
            //画横线,就是往下偏移一个分割线的高度
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        }else {
            //画竖线,就是往右偏移一个分割线的宽度
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

item_one.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=".MainActivity">

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

    <ImageView
        android:id="@+id/iv1"
        android:layout_width="100dp"
        android:layout_height="100dp" />

</LinearLayout>

item_two.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="horizontal"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_title2"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:text="111111111"/>

    <ImageView
        android:id="@+id/iv2"
        android:layout_width="200dp"
        android:layout_height="150dp"
         android:src="@mipmap/ic_launcher"/>

</LinearLayout>

adapter层的适配器NewsAdapter

package com.bw.zhoukao1.adapter;

import android.content.Context;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bw.zhoukao1.R;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * @Auther: jiangnengbao
 * @Date: 2019/2/18 16:37:27
 * @Description:
 */
public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    public interface OnRecyclerViewItemLongClickLisenter {

        void onRecyclerViewItemLongClick(int position);
    }

    private OnRecyclerViewItemLongClickLisenter longClickLisenter;

    public void setOnRecyclerViewItemLongClickLisenter(OnRecyclerViewItemLongClickLisenter longClickLisenter) {
        this.longClickLisenter = longClickLisenter;
    }

    private static int TYPE_ONE = 0;
    private static int TYPE_TWO = 1;

    Context context;
    JSONArray datas;

    public NewsAdapter(Context context, JSONArray datas) {
        this.context = context;
        this.datas = datas;
    }

    //返回条目类型
    @Override
    public int getItemViewType(int position) {
        if (position % 2 == 0) {
            return TYPE_ONE;
        } else {
            return TYPE_TWO;
        }

    }

    //创建ViewHolder
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int type) {
        //根据类型判断条目布局样式
        if (type == TYPE_ONE) {
            View view1 = LayoutInflater.from(context).inflate(R.layout.item_one, null, false);


            final ViewHolder1 viewHolder1 = new ViewHolder1(view1);

            //长按系统view的监听
            view1.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {

                   //获取view对应的位置
                    int layoutPosition = viewHolder1.getLayoutPosition();
                    //接口回调数据
                    if (longClickLisenter != null) {
                        longClickLisenter.onRecyclerViewItemLongClick(layoutPosition);
                    }

                    return true;
                }
            });
            return viewHolder1;
        } else {
            View view2 = LayoutInflater.from(context).inflate(R.layout.item_two, null, false);
            final ViewHolder2 viewHolder2 = new ViewHolder2(view2);
            //长按系统view的监听
            view2.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {

                    //获取view对应的位置
                    int layoutPosition = viewHolder2.getLayoutPosition();

                    if (longClickLisenter != null) {
                        //回调条目对应的位置
                        longClickLisenter.onRecyclerViewItemLongClick(layoutPosition);
                    }

                    return true;
                }
            });
            return viewHolder2;

        }


    }

    //给控件赋值
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {

        int itemViewType = getItemViewType(i);
        if (itemViewType == TYPE_ONE) {

            ViewHolder1 viewHolder1 = (ViewHolder1) viewHolder;

            try {
                JSONObject jsonObject = datas.getJSONObject(i);
                viewHolder1.tv_title1.setText(jsonObject.getString("title"));
                JSONArray pics = jsonObject.getJSONArray("pics");
                String imageUrl = (String) pics.get(0);
                Glide.with(context).load("http://365jia.cn/uploads/" + imageUrl).into(viewHolder1.iv1);

            } catch (JSONException e) {
                e.printStackTrace();
            }


        } else {
            ViewHolder2 viewHolder2 = (ViewHolder2) viewHolder;
            try {
                JSONObject jsonObject = datas.getJSONObject(i);
                viewHolder2.tv_title2.setText(jsonObject.getString("title"));
                JSONArray pics = jsonObject.getJSONArray("pics");
                String imageUrl = (String) pics.get(0);
                Glide.with(context).load("http://365jia.cn/uploads/" + imageUrl).into(viewHolder2.iv2);
            } catch (JSONException e) {
                e.printStackTrace();
            }


        }
    }

    @Override
    public int getItemCount() {
        return datas.length();

    }


   //删除对应条目数据
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public void removeItem(int position){
       //操作数据源
        datas.remove(position);
        //刷新
        notifyDataSetChanged();

    }

    //自定义ViewHolde
    public class ViewHolder1 extends RecyclerView.ViewHolder {

        private final TextView tv_title1;
        private final ImageView iv1;

        public ViewHolder1(@NonNull View itemView) {
            super(itemView);
            tv_title1 = itemView.findViewById(R.id.tv_title1);
            iv1 = itemView.findViewById(R.id.iv1);
        }
    }


    public class ViewHolder2 extends RecyclerView.ViewHolder {
        private final TextView tv_title2;
        private final ImageView iv2;

        public ViewHolder2(@NonNull View itemView) {
            super(itemView);
            tv_title2 = itemView.findViewById(R.id.tv_title2);
            iv2 = itemView.findViewById(R.id.iv2);
        }
    }
}

依赖

    implementation 'com.android.support:recyclerview-v7:28.+'
    implementation 'com.squareup.okio:okio:1.5.0'
    implementation 'com.squareup.okhttp3:okhttp:3.2.0'
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
    implementation project(':xrecyclerview')

权限

   <uses-permission android:name="android.permission.INTERNET"></uses-permission>
内容概要:本文介绍了奕斯伟科技集团基于RISC-V架构开发的EAM2011芯片及其应用研究。EAM2011是一款高性能实时控制芯片,支持160MHz主频和AI算法,符合汽车电子AEC-Q100 Grade 2和ASIL-B安全标准。文章详细描述了芯片的关键特性、配套软件开发套件(SDK)和集成开发环境(IDE),以及基于该芯片的ESWINEBP3901开发板的硬件资源和接口配置。文中提供了详细的代码示例,涵盖时钟配置、GPIO控制、ADC采样、CAN通信、PWM输出及RTOS任务创建等功能实现。此外,还介绍了硬件申领流程、技术资料获取渠道及开发建议,帮助开发者高效启动基于EAM2011芯片的开发工作。 适合人群:具备嵌入式系统开发经验的研发人员,特别是对RISC-V架构感兴趣的工程师和技术爱好者。 使用场景及目标:①了解EAM2011芯片的特性和应用场景,如智能汽车、智能家居和工业控制;②掌握基于EAM2011芯片的开发板和芯片的硬件资源和接口配置;③学习如何实现基本的外设驱动,如GPIO、ADC、CAN、PWM等;④通过RTOS任务创建示例,理解多任务处理和实时系统的实现。 其他说明:开发者可以根据实际需求扩展这些基础功能。建议优先掌握《EAM2011参考手册》中的关键外设寄存器配置方法,这对底层驱动开发至关重要。同时,注意硬件申领的时效性和替代方案,确保开发工作的顺利进行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值