Android高级

一、OKHttp

OK get 异步请求

①获取ok对象

OkHttpClient okHttpClient =new OkHttpClient.Builder().build();


②获取request对象

Request request =new Request.Builder().get()

                            .url("https://www.wanandroid.com/project/list/1/json?cid=294")

                            .build();


③获取call对象      Call call = okHttpClient.newCall(request);


④call执行请求

call.enqueue(new Callback() {

@Override

    public void onFailure(Call call, IOException e) {

Log.e(TAG,"onFailure: 错误信息+get"+e.getMessage() );

}

@Override

    public void onResponse(Call call, Response response)throws IOException {

String string = response.body().string();

FoodBean foodBean =new Gson().fromJson(string, FoodBean.class);

final String title = foodBean.getData().get(0).getTitle();

Log.e(TAG,"onResponse: get"+ title);

runOnUiThread(new Runnable() {

@Override

            public void run() {

mGetEnBtn.setText(title);}});

});


ok post异步请求

①获取ok对象


②创建请求体

RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), s);


③获取request对象


④获取call对象


⑤call执行请求

请求体

①string:RequestBody.create(type,"");

②stream:new RequestBody()

③form:FormBody.builder().build();

④file

请求头、缓存、超时

请求头:reques.header() request.addHeader()

缓存:okHttpClient.cacha(new Cache(file,time))

超时:ok.timeout()


二、Retrofit

retrofit使用步骤

①创建接口服务类:baseURL和方法,添加依赖

StringHONE_URL ="https://www.wanandroid.com/";

@GET("article/list/0/json")

Observable getHomeData();


②创建retrofit对象

Retrofit retrofit =new Retrofit.Builder()

                        .baseUrl(ApiServer.FOOD_URL)

                        .addConverterFactory(GsonConverterFactory.create())

                        .build();


③通过retrofit对象获取接口服务对象

ApiServer apiServer = retrofit.create(ApiServer.class);


④接口服务对象调用自己的方法


⑤通过call执行请求


三,GreenDao

1,Greendao配置

2,123

3,双检锁单例模式:得到表对象

public static DbUser getInstance() {

        if (ourInstance==null){

                synchronized (DbUser.class){

                        if (ourInstance==null){

                                ourInstance=new DbUser();

                        }

                }

        }

        return ourInstance;

}

private DbUser() {

        DaoMaster.DevOpenHelper devOpenHelper =new DaoMaster.DevOpenHelper(BaseApp.getApp(),"dao.db");

        DaoMaster daoMaster =new DaoMaster(devOpenHelper.getWritableDb());

        DaoSession daoSession = daoMaster.newSession();

        dataBeanDao = daoSession.getDataBeanDao();

}

4,获取整个App的上下文


GreenDao详细配置

使用Greendao实现增删改查

// 添加代码仓库 步骤1

mavenCentral()

//greenDao生产代码插件  步骤2

    classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin

// apply plugin 步骤3

apply plugin: 'org.greenrobot.greendao'

//greenDAO配置  步骤4

    implementation 'org.greenrobot:greendao:3.2.2' // add library

    implementation 'org.greenrobot:greendao-generator:3.2.2'

//greendao配置  步骤5  在buildTypes下面添加

    greendao {

        //数据库版本号,升级时修改

        schemaVersion 1

        //生成的DAO,DaoMaster和DaoSession的包路径。默认与表实体所在的包路径相同

        daoPackage 'com.example.xts.greendaodemo.db'

        //生成源文件的路径。默认源文件目录是在build目录中的(build/generated/source/greendao)

        targetGenDir 'src/main/java'

    }

//第六步,

建bean类 实体类和数据库对应,,添加相关注解,,然后编译项目生成相关文件  锤项目

@Entity

public class Bean {

    @Id    //表示是表中的主键

    private Long id; //一定是Long型

    private String date;

    @Unique  //此字段的值唯一约束:不能重复

    private String name;

    private int step;

}

//第七步,

创建一个自己的application类,在application中完成DaoSession的初始化,避免以后重复初始化,便于使用  ,,,要配置到清单中

public class BaseApp extends Application {

    private static BaseApp sInstance;

    private DaoMaster.DevOpenHelper mHelper;

    private DaoMaster mDaoMaster;

    private DaoSession mDaoSession;

    @Override

    public void onCreate() {

        super.onCreate();

        sInstance = this;

        setDatabase();

    }

        /**

        * 设置greenDao

        */

    private void setDatabase() {

        //通过DaoMaster内部类DevOpenHelper可以获取一个SQLiteOpenHelper 对象

        // 可能你已经注意到了,你并不需要去编写「CREATE TABLE」这样的 SQL 语句,因为 greenDAO 已经帮你做了。

        // 注意:默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。

        // 所以,在正式的项目中,你还应该做一层封装,来实现数据库的安全升级。

        // 此处MyDb表示数据库名称 可以任意填写

        mHelper = new DaoMaster.DevOpenHelper(this, "MyDb", null);    // MyDb是数据库的名字,更具自己的情况修改

        SQLiteDatabase db = mHelper.getWritableDatabase();

        mDaoMaster = new DaoMaster(db);

        mDaoSession = mDaoMaster.newSession();

    }

    public static BaseApp getInstance(){

        return sInstance;

    }

    public DaoSession getDaoSession(){

        return mDaoSession;

    }

}

//第八步 

在清单中使用此BaseApp

<application

        android:name=".BaseApp"

        android:allowBackup="true"

//第九步 

使用,BeanDao beanDao = BaseApp.getInstance().getDaoSession().getBeanDao();//得到对象

完成数据库的创建,表的创建,插入数据insert

beanDao.insert(new Bean(1l,"2019-8-27","张三","添加"));


5,GreenDao升级

第一步:

复制MigrationHelper到项目,网上有不少MigrationHelper的源码,这里采用的是https://github.com/yuweiguocn/GreenDaoUpgradeHelper中的MigrationHelper,它主要是通过创建一个临时表,将旧表的数据迁移到新表中,大家可以去看下源码。

publicclassMyOpenHelperextendsDaoMaster.OpenHelper{publicMyOpenHelper(Contextcontext,Stringname,SQLiteDatabase.CursorFactoryfactory){super(context,name,factory);}@OverridepublicvoidonUpgrade(Databasedb,intoldVersion,intnewVersion){//把需要管理的数据库表DAO作为最后一个参数传入到方法中MigrationHelper.migrate(db,newMigrationHelper.ReCreateAllTableListener(){@OverridepublicvoidonCreateAllTables(Databasedb,booleanifNotExists){DaoMaster.createAllTables(db,ifNotExists);}@OverridepublicvoidonDropAllTables(Databasedb,booleanifExists){DaoMaster.dropAllTables(db,ifExists);}},BeanDao.class);}}

新建一个类,继承DaoMaster.DevOpenHelper,重写onUpgrade(Database db, int oldVersion, int newVersion)方法,在该方法中使用MigrationHelper进行数据库升级以及数据迁移。

然后使用MyOpenHelper替代DaoMaster.DevOpenHelper来进行创建数据库等操作

mSQLiteOpenHelper=newMyOpenHelper(MyApplication.getInstance(),DB_NAME,null);//建库mDaoMaster=newDaoMaster(mSQLiteOpenHelper.getWritableDatabase());mDaoSession=mDaoMaster.newSession();

第二步:

在表实体中,调整其中的变量(表字段),一般就是新增/删除/修改字段。注意:

1)新增的字段或修改的字段,其变量类型应使用基础数据类型的包装类,如使用Integer而不是int,避免升级过程中报错。

2)根据MigrationHelper中的代码,升级后,新增的字段和修改的字段,都会默认被赋予null值。

第三步:

将原本自动生成的构造方法以及getter/setter方法删除,重新Build—>Make Project进行生成。

第四步:

修改Module下build.gradle中数据库的版本号schemaVersion ,递增加1即可,最后运行app

greendao{//数据库版本号,升级时进行修改schemaVersion2daoPackage'com.dev.base.model.db'targetGenDir'src/main/java'}


四,RxJava

1,Rxjava定义:一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库。

        优点:逻辑简洁 , 实现优雅  ,  使用简单

        作用:实现异步操作

        原理:被观察者(Observable) 通过 订阅(Subscribe)按顺序发送事件 给观察者(Observer), 观察者(Observer) 按顺序接收事件 & 作出对应的响应动作。

        三大概念: 1,onNext() 接收被观察者发送的消息

                            2, onCompleted() 事件队列完结

                            3,onError ()    事件队列异常

        调度器: subscribeOn():或者叫做事件产生的线程。

                        指定 subscribe()所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程。

                        observeOn():或者叫做事件消费的线程。指定 Subscriber所运行在的线程。

        事件:

2,Rxjava使用:基本使用、链式使用

3,Rxjava结合retrofit实现网络请求

①定义接口服务的时候返回类型是Observable

②retrofit网络请求

③call请求替换为Observable订阅observer

④通过调度器控制网络请求、结果处理的线程

4,Rxjava其他操作符


五,BroadcastReceiver(广播)

1 . 定义:

            即 广播,是一个全局的监听器,属于Android四大组件之一Android 广播分为两个角色:广播发送者、广播接收者

2. 作用:

            监听 / 接收 应用App发出的广播消息,并做出响应

3. 应用场景:

            Android不同组件间的通信(含 :应用内 / 不同应用之间)多线程通信与Android系统在特定情况下的通信

模型中有3个角色:

        消息订阅者(广播接收者)

        消息发布者(广播发布者)

        消息中心(AMS,即Activity Manager Service)

自定义广播接收者BroadcastReceiver

        继承BroadcastReceiver ,重写onReceive方法

        注册(onResume),注销(onPause)

        *不注销可能会内存泄漏

        重复注册,注销也会报错

发送广播:

        用意图发送:new Intent(过滤器);(注册时和发送时的过滤器必须保持一致)

动态,静态注册的区别:

广播类型:

        普通广播(Normal Broadcast)

        系统广播(System Broadcast)

        有序广播(Ordered Broadcast)

        粘性广播(Sticky Broadcast)

        App应用内广播(Local Broadcast)


MVP,MVC

MVC:

        视图层(View):对应于xml布局文件和java代码动态view部分

        控制层(Controller):MVC中Android的控制层是由Activity来承担的,Activity本来主要是作为初始化页面,展示数据的操作,但是因为XML视图功能太弱,所以Activity既要负责视图的显示又要加入控制逻辑,承担的功能过多。

        模型层(Model):针对业务模型,建立的数据结构和相关的类,它主要负责网络请求,数据库处理,I/O的操作。

缺点

        M层和V层有连接关系,没有解耦,导致维护困难.

        Activity/Fragment中的代码过多,难以维护.

        Activity中有很多关于视图UI的显示代码,因此View视图和Activity控制器并不是完全分离的,当Activity类业务过多的时候,会变得难以管理和维护.尤其是当UI的状态数据,跟持久化的数据混杂在一起,变得极为混乱.

优点

        控制层和View层都在Activity中进行操作,数据操作方便.

        模块职责划分明确.主要划分层M,V,C三个模块.

MVC总结

具有一定的分层,model彻底解耦,controller和view并没有解耦

层与层之间的交互尽量使用回调或者去使用消息机制去完成,尽量避免直接持有

controller和view在android中无法做到彻底分离,但在代码逻辑层面一定要分清

业务逻辑被放置在model层,能够更好的复用和修改增加业务

MVP:

①概述:MVP,即是Model,View,Presenter架构模式.看起来类似MVC,其实不然.从上图能看到Model层和View层没有相连接,完全解耦.

②分层:M层:模型层(Model),此层和MVC中的M层作用类似.主要是实体类,数据库,网络等存在的层面

               V层:视图层(View),在MVC中V层只包含XML文件,而MVP中V层包含XML,Activity和Fragment三者.理论上V层不涉及任何逻辑,只负责界面的改变,尽量把逻辑处理放到M层.

                P层:通知层(Presenter),P层的主要作用就是连接V层和M层,起到一个通知传递数据的作用.

③原理:用户触碰界面触发事件,View层把事件通知Presenter层,Presenter层通知Model层处理这个事件,Model层处理后把结果发送到Presenter层,Presenter层再通知View层,最后View层做出改变.这是一整套流程.

④. MVP架构优缺点

A. 缺点

MVP中接口过多.

每一个功能,相比于MVC要多写好几个文件.

如果某一个界面中需要请求多个服务器接口,这个界面文件中会实现很多的回调接口,导致代码繁杂.

如果更改了数据源和请求中参数,会导致更多的代码修改.

额外的代码复杂度及学习成本.

B. 优点

模块职责划分明显,层次清晰,接口功能清晰.

Model层和View层分离,解耦.修改View而不影响Model.

功能复用度高,方便.一个Presenter可以复用于多个View,而不用更改Presenter的逻辑.

有利于测试驱动开发,以前的Android开发是难以进行单元测试.

如果后台接口还未写好,但已知返回数据类型的情况下,完全可以写出此接口完整的功能.


八、注解

Butterknife:

        通过注解的方式找资源

        ①添加依赖

        ②添加插件

        ③使用

EventBus:

        事件总线

        ①添加依赖

        ②注册、解注册Eventbus,接受事件的方法

                EventBus.getDefault().register(this);//注册

                EventBus.getDefault().unregister(this);//解除注册

                @Subscribe(threadMode = ThreadMode.MAIN)//接受

                public void XXX(MessageEvent messageEvent) { ...}

        ③发送事件

Event 事件

Subscriber 事件订阅者

Publisher 事件的发布者

注意

        ①普通事件粘性事件

        ②粘性事件:发送Eventbus.postAticky、接受方法注解中必须sticky=true


九、Glide

1,Glide可以加载四种资源

网络地址、sdcard、本地资源、字节流

    // 加载本地图片 

                File file = new File(getExternalCacheDir() + "/image.jpg");

                Glide.with(this).load(file).into(imageView); ​

    // 加载应用资源   

            int resource = R.drawable.image;   

            Glide.with(this).load(resource).into(imageView);    ​

    // 加载二进制流    

            byte[] image = getImageBytes();    

            Glide.with(this).load(image).into(imageView);    ​

    // 加载Uri对象    

            Uri imageUri = getImageUri();   

             Glide.with(this).load(imageUri).into(imageView);

2,占位图

        预占位图: .placeholder(R.drawable.loading);

        错误占位图: .error(R.drawable.error)

                                .diskCacheStrategy(DiskCacheStrategy.NONE);

3,缓存

硬盘缓存:总共五种,默认AutoMatic

            .diskCacheStrategy(DiskCacheStrategy.NONE)//关闭Glide的硬盘缓存机制

内存缓存:默认有

            .skipMemoryCache(true) //传入参数为true时,则关闭内存缓存。

4,指定图片的格式:asBitmap、asGif(必须放在with后边)

        .asBitmap()//只加载静态图片,如果是gif图片则只加载第一帧。

        .asGif()//加载动态图片,若现有图片为非gif图片,则直接加载错误占位图。

5,指定图片大小

        .override(100, 100)//指定图片大小

6,下载图片

        .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);

        final File imageFile = target.get();

7,图形变换

圆形、圆角、三方

//圆角:

        RoundedCorners roundedCorners = new RoundedCorners(8);

        requestOptions.transform(roundedCorners);

//圆型

RequestOptions options = new RequestOptions() .circleCrop();


十、Fresco

十一、Matrix和ColorMatrix

矩阵:对于图片的变换处理

Bitmap baseBitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() +"/Pictures/b.jpg");

//因为要将图片放大,所以要根据放大的尺寸重新创建Bitmap,Android不允许对原图进行处理

BitmapafterBitmap=Bitmap.createBitmap(

(int) (baseBitmap.getWidth()*x),

(int) (baseBitmap.getHeight()*y), baseBitmap.getConfig());

Canvascanvas=newCanvas(afterBitmap);

//初始化Matrix对象

Matrixmatrix=newMatrix();

//根据传入的参数设置缩放比例

matrix.setScale(x, y);

//根据缩放比例,把图片draw到Canvas上

canvas.drawBitmap(baseBitmap, matrix, paint);

iv.setImageBitmap(afterBitmap);


setTranslate(float dx,float dy):控制Matrix进行位移。

setSkew(float kx,float ky):控制Matrix进行倾斜,kx、ky为X、Y方向上的比例。

setSkew(float kx,float ky,float px,float py):控制Matrix以px、py为轴心进行倾斜,kx、ky为X、Y方向上的倾斜比例。

setRotate(float degrees):控制Matrix进行depress角度的旋转,轴心为(0,0)。

setRotate(float degrees,float px,float py):控制Matrix进行depress角度的旋转,轴心为(px,py)。

setScale(float sx,float sy):设置Matrix进行缩放,sx、sy为X、Y方向上的缩放比例。

setScale(float sx,float sy,float px,float py):设置Matrix以(px,py)为轴心进行缩放,sx、sy为X、Y方向上的缩放比例。


十二、LRUCache

原理(*****)

通过案例学习entry顺序

通过demo掌握三级缓存的原理

①什么是三级缓存

②内存缓存工具类

③硬盘缓存工具类


十三、文件上传下载

1.ok上传

2.Retrofit上传

3.HTTPURLCollection上传

4.OkHttp下载

5.HTTPURLCollection下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容