1. 程式人生 > >使用MVP模式+Retrofit+Fresco載入網路資料

使用MVP模式+Retrofit+Fresco載入網路資料

今天寫了一個使用MVP架構模式的網路請求資料的Demo,網路請求的是使用了Retrofit請求

自帶了Gson解析,Fresco載入網路圖片,使用recyclerview展示資料。首先,先把需要用到的依賴匯入

compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:recyclerview-v7:26.+'
    compile 'com.squareup.okhttp3:okhttp:3.9.0'
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'io.reactivex.rxjava2:rxjava:2.1.6'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
    compile 'com.facebook.fresco:fresco:1.5.0'

先做準備工作,建立一個App,初始化Fresco
public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        Fresco.initialize(this);
    }
}

不要忘了在清單檔案裡面配置App,還有不要忘了加網路許可權,

main_layout

<?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="com.example.a1106lianxi.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#FF4081">

        <TextView
            android:id="@+id/tv_f"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:text="←"
            android:textColor="#ffffff"
            android:textSize="30sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_centerVertical="true"
            android:paddingLeft="10dp"
            android:paddingRight="15dp"
            android:text="我的收藏"
            android:textColor="#ffffff"
            android:textSize="15sp" />

        <TextView
            android:id="@+id/tv_bian"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:paddingLeft="10dp"
            android:paddingRight="15dp"
            android:text="編輯"
            android:textColor="#ffffff"
            android:textSize="15sp" />

    </RelativeLayout>
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv"

            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </android.support.v7.widget.RecyclerView>
    </FrameLayout>
</LinearLayout>
佈局寫好了再去實現view層的介面,然後MainActivity實現介面,重寫介面的方法
public interface IMusicView {
    public void showData(List<MusicBean.SongListBean> bean);
}
model建立介面,實現方法
public interface IMusicModel {
    public Retrofit getUrl(String path);
}
這裡用到了一個攔截器,資料來源必須加這個攔截器才能出資料
public class LoggingInterceptor implements Interceptor {
    private static final String UA = "User-Agent";

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request()
                .newBuilder()
                .addHeader(UA, makeUA())
                .build();
        return chain.proceed(request);
    }

    private String makeUA() {
        String s = Build.BRAND + "/" + Build.MODEL + "/" + Build.VERSION.RELEASE;
        return Build.BRAND + "/" + Build.MODEL + "/" + Build.VERSION.RELEASE;
    }

}
把這個攔截器加到Retrofit裡面去

public class MusicModel implements IMusicModel {
    @Override
    public Retrofit getUrl(String path) {
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new LoggingInterceptor())
                .build();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(path)
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();
        return retrofit;
    }
}

presenter
public class MusicPresenter {
    Context context;
    IMusicModel model;
    IMusicView view;
    List<MusicBean.SongListBean> list;

    public MusicPresenter(Context context, IMusicView view) {
        this.context = context;
        this.view = view;
        model = new MusicModel();
    }
    public void showdata(){
        Retrofit rf = model.getUrl("http://tingapi.ting.baidu.com/");
        MusicService ms = rf.create(MusicService.class);
        ms.getda().enqueue(new Callback<MusicBean>() {
            @Override
            public void onResponse(Call<MusicBean> call, Response<MusicBean> response) {
                MusicBean mb = response.body();
                list = new ArrayList<MusicBean.SongListBean>();
                list.addAll(mb.getSong_list());
                Log.i("+++++list++++++", "onResponse: "+list.toString());
                view.showData(list);
            }

            @Override
            public void onFailure(Call<MusicBean> call, Throwable t) {

            }
        });
    }
}

需要建立一個service介面
public interface MusicService {
    @GET("v1/restserver/ting?method=baidu.ting.billboard.billList&type=1&size=20&offset=0")
    Call<MusicBean> getda();
}
註解的方式
建立recyclerview介面卡,建立子佈局
public class MusicAdapter extends RecyclerView.Adapter<MusicAdapter.MyViewHolder> {

    List<MusicBean.SongListBean> list;
    Context context;

    public MusicAdapter(List<MusicBean.SongListBean> list, Context context) {
        this.list = list;
        this.context = context;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(context, R.layout.item,null);
        MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.tv.setText(list.get(position).getTitle());
        Uri uri = Uri.parse(list.get(position).getPic_small());
        holder.iv.setImageURI(uri);
    }

    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder {

        TextView tv;
        ImageView iv;

        public MyViewHolder(View itemView) {
            super(itemView);
            tv = itemView.findViewById(R.id.tv_title);
            iv = itemView.findViewById(R.id.iv_title);
        }
    }
}

佈局
<?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="match_parent"
    android:orientation="horizontal">
    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/iv_title"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:src="@mipmap/ic_launcher"/>
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="哈哈哈哈哈哈哈哈哈"/>

</LinearLayout>


主方法呼叫,與presenter互動

public class MainActivity extends Activity implements IMusicView, View.OnClickListener {

    private RecyclerView rv;
    List<MusicBean.SongListBean> mlist;
    private TextView mFTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        MusicPresenter presenter = new MusicPresenter(this, this);
        presenter.showdata();
    }

    private void initView() {
        rv = (RecyclerView) findViewById(R.id.rv);
        mFTv = (TextView) findViewById(R.id.tv_f);
        mFTv.setOnClickListener(this);
    }

    @Override
    public void showData(List<MusicBean.SongListBean> bean) {
        mlist = bean;
        rv.setLayoutManager(new LinearLayoutManager(this));
        MusicAdapter adapter = new MusicAdapter(mlist, this);
        rv.setAdapter(adapter);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_f:
                Tuichu();
                break;
            default:
                break;
        }
    }
    private void Tuichu() {
        new AlertDialog.Builder(this)
                .setTitle("確認")
                .setMessage("確認要刪除嗎?")
                .setPositiveButton("是", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        finish();
                    }
                })
                .setNegativeButton("否", null)
                .show();
    }
}