Glide工具类/OkGo网络请求/MVP请求数据/Retrofit+RxJava/ARouter/补间动画/轮播图等等等等等 记录一下~~

PhaseTwo(Android)

okgo

okhttp的封装 简易版Okhttp
这里继承了上一个项目中的BaseActivity,如果不明白的点下面的链接,并打开PhaseTwo(Android)
上一期的Java-Android.

package com.bawei.zhuangao2.day3;


import android.Manifest;
import android.annotation.SuppressLint;
import android.graphics.BitmapFactory;
import android.view.View;
import android.widget.ImageView;

import com.bawei.zhuangao2.R;
import com.bawei.zhuangao2.day1.HeadInterceptor;
import com.bawei.zhuangao2.day2.base.BaseActivity;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.PermissionUtils;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.cache.CacheMode;
import com.lzy.okgo.callback.FileCallback;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Response;

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

import java.io.File;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
//一样继承于BaseActivity
public class OkGoActivity extends BaseActivity {
    //用于下载图片展示
    private ImageView coverIv;

    /**
     * 绑定主要视图
     * @return
     */
    @Override
    public int bandLayout() {
        return R.layout.activity_okhttp;
    }

    /**
     * 初始化控件 并设置点击事件
     */
    @Override
    public void initView() {
        //获取隐私权限(这里隐私权限指的是:手机联系人,读写SD卡,手机信息等等)
        //这里获取了写入SD卡的权限
        PermissionUtils.permission(Manifest.permission.WRITE_EXTERNAL_STORAGE).request();

        findViewById(R.id.btn1).setOnClickListener(this);
        findViewById(R.id.btn2).setOnClickListener(this);
        findViewById(R.id.btn3).setOnClickListener(this);
        findViewById(R.id.btn4).setOnClickListener(this);
        findViewById(R.id.btn5).setOnClickListener(this);
        findViewById(R.id.btn6).setOnClickListener(this);
        coverIv = findViewById(R.id.image);
    }


    @Override
    public void initData() {

    }

    /**
     * 点击事件
     * @param v
     */
    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn1:
                //Get方式获取
                OkGo.<String>get("https://gank.io/api/v2/banners").execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        //对Response 做了解析
                        //这里还是异步线程
                        LogUtils.d(response.body());
                    }
                    @Override
                    public void onCacheSuccess(Response<String> response) {
                        super.onCacheSuccess(response);
                        LogUtils.d("onCacheSuccess" + response.body());
                    }
                });

                break;
            case R.id.btn2:
                //Post Json 通过upJson("")提交代码
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("username", "1234567");
                    jsonObject.put("pwd", "123456");
                    jsonObject.put("sex", "1");
                    jsonObject.put("birthday", "2000-9-9");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                OkGo.<String>post("http://39.98.153.96:8082/api/WeekTest/register")
                        .upJson(jsonObject.toString()).execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        //Response 对做了解析
                        //这里还是异步线程
                        LogUtils.d(response.body());
                    }
                });
                break;
            case R.id.btn3:
                //Post From
                //username=1903001&pwd=123456
                OkGo.<String>post("http://39.98.153.96:8082/api/WeekTest/login?username=1903001&pwd=123456")
                        .params("username", "1903001")
                        .params("pwd", "123456")
                        .execute(new StringCallback() {
                            @Override
                            public void onSuccess(Response<String> response) {
                                //Response 对做了解析
                                //这里还是异步线程
                                LogUtils.d(response.body());
                            }
                        });
                break;
            case R.id.btn4:
                //下载
                OkGo.<File>get("https://pic.downk.cc/item/5e7b64fd504f4bcb040fae8f.jpg").execute(new FileCallback() {
                    @Override
                    public void onSuccess(final Response<File> response) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                LogUtils.d(response.body().getPath());
                                coverIv.setImageBitmap(BitmapFactory.decodeFile(response.body().getPath()));
                            }
                        });
                    }
                });
                break;
            case R.id.btn5:

                break;
            case R.id.btn6:
                //文件上传
                File file = new File("/storage/emulated/0/download/1382400000b859e1c2339");
                coverIv.setImageBitmap(BitmapFactory.decodeFile(file.getPath()));
                OkGo.<String>post("http://117.51.155.210/hfs/")
                        //发送格式为file
                        .params("file",file)
                        //分段发送
                        .isMultipart(true)
                        .execute(new StringCallback() {
                            @Override
                            public void onSuccess(Response<String> response) {
                                LogUtils.d(response.body());
                            }
                        });
                break;
        }
    }
}


Glide工具

认识Glide
Glide是一个图片加载框架,功能强大,一般用于一些视图显示图片,从url中加载图片等等,也可以进行裁剪图片,达到视觉美观

Glide方法类

/**
 * 单例 双重校验 双重锁
 */
public class ImageManger {

    public void showImage(String url, ImageView view){
        Glide.with(Utils.getApp()).load(url)
                //关闭缓存
                .skipMemoryCache(true)
                //关闭磁盘缓存
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                //加载过程显示
                .placeholder(R.mipmap.ic_launcher)
                //加载失败显示
                .error(R.mipmap.ic_launcher)
                .into(view);
    }

    public void showR(String url, ImageView view,int radius){
        Glide.with(Utils.getApp()).load(url)
                .transform(new RoundedCorners(radius))
                //加载过程显示
                .placeholder(R.mipmap.ic_launcher)
                //加载失败显示
                .error(R.mipmap.ic_launcher)
                .into(view);
    }

    public void showC(String url, ImageView view){
        Glide.with(Utils.getApp()).load(url)
                //圆形
                .circleCrop()
                .into(view);
    }

    //多线程可见
    private static volatile ImageManger imageManger;

    //饿汉式单例
    public static ImageManger getInstance(){
        if (imageManger==null){
            //这里上锁
            synchronized (ImageManger.class){
                if (imageManger==null){
                    imageManger=new ImageManger();
                }
            }
        }
        return imageManger;
    }
}

Activity类


public class GlideActivity extends BaseActivity {
    private android.widget.ImageView actGlideIv01;
    private android.widget.ImageView actGlideIv02;
    private android.widget.ImageView actGlideIv03;

    //初始化主视图
    @Override
    public int bandLayout() {
        return R.layout.activity_glide;
    }

    //初始化控件
    @Override
    public void initView() {

        actGlideIv01 = findViewById(R.id.act_glide_iv_01);
        actGlideIv02 = findViewById(R.id.act_glide_iv_02);
        actGlideIv03 = findViewById(R.id.act_glide_iv_03);
    }

    //加载数据(显示图片)
    @Override
    public void initData() {
        //实例化调用方法 完成Glide加载
        ImageManger imageManger = new ImageManger();
        imageManger.showImage("https://pic.downk.cc/item/5e7b64fd504f4bcb040fae8f.jpg",actGlideIv01);
        imageManger.showC("https://pic.downk.cc/item/5e7b64fd504f4bcb040fae8f.jpg",actGlideIv02);
        imageManger.showR("https://pic.downk.cc/item/5e7b64fd504f4bcb040fae8f.jpg",actGlideIv03,50);

    }
}

MVP

在MVC中,View层是可直接调用Model层的,当发生一些特殊的情况时,无法及时更换网络请求
而MVP中则可以,MVP的主要目的是解耦,P层用于调用M层,V层则用来访问P层

内容较多:可以参考Github网站 > MVP整合框架

MVP分为:

(数据访问层)
Model层: 用于进行数据请求,一般用P层调用其中方法

(连接层)
Presenter层: 中文翻译为"主持人",一般用于连接M层和V层, V层调用P层, P层再调用M层

(视图层)
View层:用于视图展示, 继承回调接口等 调用P层中方法获取数据

目录
请添加图片描述

Base_lib

一个library组件 其中的抽象类用于被继承, 用于自定义 更加的方便写MVP

在这里插入图片描述

基础model层

(接口)

public
interface IModel {
    void destroy();
}

(抽象实现类)

//销毁方法
public abstract
class BaseModel implements IModel {
    @Override
    public void destroy() {

    }
}

基础View层

(IActivity 基础activity接口)

public
interface IActivity {
    //用于初始化视图
    void initView();
    //用于加载数据
    void initData();

    //用于绑定视图时使用(获取视图)
    int bindLayout();
}

(IView 基础view层接口)

public
interface IView {
    //用于显示进度条
    void showLoading();
    //用于隐藏进度条
    void hideLoading();

    //用于便捷Toast信息
    void showToast(String msg);
}

(BaseActivity 基础activity抽象实现类)

/**
 * 和正常Activity一样继承AppCompatActivity 需要实现activity的接口 和 视图层的接口
 */
public abstract
class BaseActivity extends AppCompatActivity implements IActivity,IView {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(bindLayout());   //这里调用获取视图方法 用于设置主视图

        //初始化视图
        initView();
        //初始化数据
        initData();
    }

    /**
     * Toast信息
     * @param msg 需要Toast的信息
     */
    @Override
    public void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
}

(IFragment 基础fragment接口)

public
interface IFragment extends IActivity {
    //方便Fragment 初始化组件
    <T extends View> T findViewById(@IdRes int id);
}

(BaseFragment 基础fragment抽象实现类)


public abstract
class BaseFragment extends Fragment implements IView,IFragment {

    private View view;

    /**
     * 创建视图时调用
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //这里绑定主视图
        view = inflater.inflate(bindLayout(),container,false);
        //返回主视图
        return view;
    }

    /**
     * 创建视图后调用
     * @param view
     * @param savedInstanceState
     */
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        //初始化视图
        initView();

        //初始化数据
        initData();
    }

    /**
     * 实现findViewById方法
     * @param id
     * @param <T>
     * @return
     */
    @Override
    public <T extends View> T findViewById(int id) {
        return view.findViewById(id);
    }
}

基础Presenter层

(IPresenter 基础 P层接口)

public
interface IPresenter{
    //销毁方法
    void destroy();
}

(IPresenter基础 P层抽象实现类)

//创建泛型 一个转型V层,另一个M层
public abstract
class BasePresenter<V extends IView,M extends IModel> implements IPresenter {
    //创建两个继承类可调用的变量
    protected V view;
    protected M model;

    //构造方法
    public BasePresenter(V view, M model) {
        this.view = view;
        this.model = model;
    }

    //销毁方法
    @Override
    public void destroy() {
        if (model!=null){
            model.destroy();
            model = null;
        }
    }
}

app主要模块

描述

Api接口

//Api接口 用于编写Retrofit调用的方法
public
interface Api {
    /**
     * Get方式获取数据
     * @param url 用于加载的url的后缀(主要部分在Utils层中)
     * @return
     */
    @GET
    Observable<FoodEntity> getFood(@Url String url);

    /**
     * 另外一种写法 可以把url后缀写为固定值 参数自己传
     * @param page page参数 会自动给到url中作为参数
     * @return
     */
    @GET("dish_list.php?stage_id=1&limit=20")
    Observable<FoodEntity> getFood(@Query("page")int page);
}

Utils层

(HttpFoodUtils单例类 初始化retrofit)

/**
 * 网络请求数据 单例类
 */
public
class HttpFoodUtils {
    private static HttpFoodUtils utils;
    private Retrofit retrofit;

    /**
     * 饿汉式单例
     * @return
     */
    public static HttpFoodUtils getInstance() {
        if (utils==null){
            utils = new HttpFoodUtils();
        }
        return utils;
    }

    //初始化 类似单例
    public Retrofit getRetrofit() {
        if (retrofit==null){
            retrofit = new Retrofit.Builder()
                    //这里填写主要url
                    .baseUrl("http://www.qubaobei.com/ios/cf/")
                    //添加Okhttp拦截器 并设置超时时间
                    .client(new OkHttpClient.Builder()
                            .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                            .readTimeout(2, TimeUnit.MINUTES)
                            .connectTimeout(2,TimeUnit.MINUTES)
                            .writeTimeout(2,TimeUnit.MINUTES)
                            .build())
                    //添加解析工厂和回调工厂
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    //创建
                    .build();
        }
        //返回
        return retrofit;
    }
}

IContract

public
interface IContract {
    //获取数据的视图接口
    interface IFoodView extends IView{
        /**
         * 显示数据
         * @param list 展示的数据集合
         */
        void showFood(List<FoodEntity.DataBean> list);
    }

    //获取数据的M层接口
    interface IFoodModel extends IModel{
        /**
         * 获取数据
         * @param url 后缀链接
         * @param observer 观察者
         */
        void getFood(String url,Observer<FoodEntity> observer);
    }
}

M层

获取数据 网络请求的方法 调用Retrofit中的单例方法 实现API.class中的方法

public
class FoodModel extends BaseModel implements IContract.IFoodModel {

    //获取数据 网络请求的方法 调用Retrofit中的单例方法 实现API.class中的方法 并回调观察者
    @Override
    public void getFood(String url,Observer<FoodEntity> observer) {
        HttpFoodUtils.getInstance()
                .getRetrofit()
                .create(Api.class)
                .getFood(url)
                //RxJava框架
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(observer);
    }

    @Override
    public void destroy() {
        //销毁方法
    }
}

P层

/**
 * P层
 */
public
class FoodPresenter extends BasePresenter<IContract.IFoodView, IContract.IFoodModel> {

    private Disposable disposable;

    public FoodPresenter(IContract.IFoodView view, IContract.IFoodModel model) {
        super(view, model);
    }

    public void getFood(String url){
        model.getFood(url, new Observer<FoodEntity>() {
            @Override
            public void onSubscribe(Disposable d) {
                disposable = d;     //设为全局
            }

            @Override
            public void onNext(FoodEntity foodEntity) {
                view.showFood(foodEntity.getData());
            }

            @Override
            public void onError( Throwable e) {
                ToastUtils.showShort(e.getMessage().toString());
                disposable.dispose();       //遇到错误后 杀死d 断开M层和V层的连接 防止内存泄漏
            }

            @Override
            public void onComplete() {
                disposable.dispose();       //方法执行完毕后 断开连接
            }
        });
    }
}

V层

主视图 用于显示数据 调用P层中的方法获取数据

public class MainActivity extends BaseActivity implements IContract.IFoodView, OnRefreshLoadMoreListener, OnRefreshListener, OnItemClickListener, OnItemLongClickListener {

    //Recycler的适配器(用于适配数据)
    private RecyclerAdapter recyclerAdapter;

    //RecyclerView展示数据控件
    private androidx.recyclerview.widget.RecyclerView mainRv;
    //P层
    private FoodPresenter foodPresenter;

    //页码和数量(用于分页 改变Url中的参数)
    private int page = 1,count = 20;
    //刷新控件
    private com.scwang.smart.refresh.layout.SmartRefreshLayout mainRefresh;

    //是否用于刷新
    private boolean isRefresh = false;
    //整合的数据
    private List<FoodEntity.DataBean> dataBeans;

    /**
     * 初始化控件和一些全局变量对象
     */
    @Override
    public void initView() {
        foodPresenter = new FoodPresenter(this,new FoodModel());
        mainRv = findViewById(R.id.main_rv);
        mainRv.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));
        mainRefresh = findViewById(R.id.main_refresh);
        mainRefresh.setOnRefreshListener(this);
        mainRefresh.setOnLoadMoreListener(this);
    }

    /**
     * 开始使用P层的getFood方法获取数据
     */
    @Override
    public void initData() {
        foodPresenter.getFood("dish_list.php?stage_id=1&limit="+count+"&page="+page);
    }

    //绑定主视图(必写)
    @Override
    public int bindLayout() {
        return R.layout.activity_main;
    }

    /**
     * 由于没写进度条 所以空闲
     */
    @Override
    public void showLoading() {

    }

    /**
     * 由于没写进度条 所以空闲
     */
    @Override
    public void hideLoading() {

    }


    /**
     * 显示数据(回调方法)
     * @param list 展示的数据集合
     */
    @Override
    public void showFood(List<FoodEntity.DataBean> list) {
        //调用初始化适配器方法
        initAdapter(list);
    }

    /**
     * 上拉加载更多
     * @param refreshLayout
     */
    @Override
    public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
        //把是否刷新改为否
        isRefresh = false;
        //页码+1
        ++page;
        //并获取数据
        foodPresenter.getFood("dish_list.php?stage_id=1&limit="+count+"&page="+page);
    }

    /**
     * 下拉刷新
     * @param refreshLayout
     */
    @Override
    public void onRefresh(@NonNull RefreshLayout refreshLayout) {
        //把是否刷新改为是
        isRefresh = true;
        //页码=1(重新开头)
        page = 1;
        //获取数据
        foodPresenter.getFood("dish_list.php?stage_id=1&limit="+count+"&page="+page);
    }

    /**
     * 初始化适配器
     * @param list 回调回来的数据
     */
    private void initAdapter(List<FoodEntity.DataBean> list) {
        //判断适配器是否为空(是否是刚运行加载的数据)
        if (recyclerAdapter==null){
            //是的话就初始化 并设置点击事件和适配
            recyclerAdapter = new RecyclerAdapter(list);
            recyclerAdapter.setOnItemClickListener(this);
            recyclerAdapter.setOnItemLongClickListener(this);
            mainRv.setAdapter(recyclerAdapter);
        }else {
            //不是的话 判断是否为刷新
            if (isRefresh) {
                //是刷新就清空适配器
                recyclerAdapter.getData().clear();
            }
            //然后正常添加适配数据 并刷新数据(不管是不是刷新 都会执行)
            recyclerAdapter.getData().addAll(list);
            recyclerAdapter.notifyDataSetChanged();
        }

        //最后将整合全局数据 改为 设配器其中的数据
        dataBeans = recyclerAdapter.getData();

        //结束刷新加载动画
        mainRefresh.finishRefresh();
        mainRefresh.finishLoadMore();

    }

    /**
     * 条目点击事件
     * @param adapter
     * @param view
     * @param position
     */
    @Override
    public void onItemClick(@NonNull @NotNull BaseQuickAdapter<?, ?> adapter, @NonNull @NotNull View view, int position) {
        //使用ARouter跳转并传值(跳转到详情页)需要在Application中初始化 “ARouter.init(this);”
        ARouter.getInstance().build("/test/details")
                .withSerializable("object",dataBeans.get(position))
                .navigation();
    }

    /**
     * 条目长按点击事件
     * @param adapter
     * @param view
     * @param position
     * @return
     */
    @Override
    public boolean onItemLongClick(@NonNull @NotNull BaseQuickAdapter adapter, @NonNull @NotNull View view, int position) {
        dataBeans.remove(position);
        recyclerAdapter.notifyItemRemoved(position);
        showToast("删除成功");
        return true;
    }
}

到此MVP结束

补间动画

作用于View控件的动画
补间动画系统自带 已经封装好的动画类,可以直接使用简单方便

请添加图片描述

intent使用(不是简单跳转页面)

可以拨号 发消息 跳转相机 从图库选择一张图片等等

权限需要自己添加:拨号权限,读取联系人权限,相机拍照权限等等

请添加图片描述

背景模糊

导入以下依赖

compile 'jp.wasabeef:blurry:3.0.0'

非作者编写

轮播图banner

banner是一个已经封装好的轮播图类,可以直接使用简单方便

请添加图片描述

侧拉框

一个可以从侧边划出来的视图

需要导入Moudle “lib_slide”
百度网盘链接:lib_slide 提取码:1233

请添加图片描述

手机验证码(EditText自动跳转)

//文字监听
editText.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    if (before > count){

                    }else{
                        
                        //设置本身失去焦点
                        editText.clearFocus();
                        
                        if (nextEditText >= list.size()){
                            return;
                        }
                        list.get(nextEditText).requestFocus();
                    }
                }



//键盘按键监听
editText.setOnKeyListener(new OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                //判断是否为删除键
                    if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_DEL){
                        if (nowEditText == 0){
							//如果删除到最后一个了 就清空
                            editText.setText("");
							//并且还是获取自身焦点(没有什么重要)
                            list.get(nowEditText).requestFocus();
                            return false;
                        }
                        if (editText.getText().toString().isEmpty() && !list.get(lastEditText).getText().toString().isEmpty()){
							//本身失去焦点
                            editText.clearFocus();
                            //上一个清空
                            list.get(lastEditText).setText("");
                            //上一个获取焦点
                            list.get(lastEditText).requestFocus();
                        }
                    }
                    return false;
                }
            });

注解传值规范

@IntDef({AuthCodeView.FOUR_DIGIT,AuthCodeView.SIX_DIGIT})
@Retention(RetentionPolicy.SOURCE)
public @interface InputSize {

}

将以上的注解放到属性上,此属性只能传入AuthCodeView.FOUR_DIGIT,AuthCodeView.SIX_DIGIT 两个参数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值