常用框架

一、注解的使用:
1.元注解:

   @Document : Javadoc工具会将此注解标记元素的注解信息包含在javadoc中,默认是不包含在里面的
    @Target
    @Retention
    @Inherited : 可以继承


2.butterknife的原理:butterknife使用的是java的注解处理技术,也就是在代码编译的时候,编译成字节码的时候,在编译期间就已经处理好了各个view的初始化和相应的点击事件,

通过APT可以生成生成Java代码,生成Java代码是调用javapoet库生成的,而不是在运行期间去做的,并不是通过反射实现,整个注解是运行在CLSSS阶段的,所以性能优势是非常高的

 

3处理注解的流程:

a.首先声明注解的生命周期为CLASS

b.ButterKnifeProcessor继承AbstractProcess类

c.再调用AbstractProcessor的process的方法


4.绑定view的时候,为什么不能private和static。
答:因为性能问题,如图我们我们把这个view设置成private,那么这个框架他就不能通过注解的方式来获取了,只能通过反射来获取,
此时不管你的性能有多快,都会影响性能。这是必须注意并且避免的。这也就是和其他注解方式不通的一点


5.ButterKnife.bind(this)必须在setContentView()之后调用,否则会绑定失效的

 

6.注解是如何实现的

1.process方法里面它会先调用findAndParseTargets(),这个方法里面创建了一个LinkHaspMap作为存储ID和view的,同时调用getElementsAnnotatedWith()它主要是遍历所有的BindView的所有注解对象,得到相应注解以后调用parseBindView将他们转化,

这个转换过程中就包含ElementType可以获取view的对象,通过BindVIew.getAnnotation.value来获取ID的数值,把获取的ID数值和view保存在LinkedHashMap里面,这样view和ID就可以绑定到一起

然后里面有个方法来判断定义private或者static、或者包名以Android或者Java作为开头都会报出错误

 

7.findViewById是如何实现的:

process在生成java file文件之前会createBindingConstructor(),它在编译阶段可以把我们注解转换成findViewById、

onClick、onItemClick这些不同事件判断处理,处理完之后就通过addViewBing这个方法来最后完成findViewById、事件的点击等的实现。

 

@BindView(R.id.textview)

@OnClick

@OnItemClick

@ButterKnife.bind(this)

 

8.LinkHashMap和HashMap的区别

 LinkHashMap : 是HashMap的一个子类,它存储是有序的。

 HashMap : 它的存储是无序的。

 LinkHashMap和HashMap处理速度:LinkHashMap遍历速度受实际数量影响,而HashMap遍历速度受容量的影响

 

9.守护线程: 主线程结束后,如果没有用户线程,守护进程也会自动结束,它比用户线程优先级低

 用户线程:主线程结束后,守护线程也还会一直存活的。

----------------------------------------------------------------------------------------------------------------------------------------------------

二、OkHttp的全面用法:

    1. Get的请求:  例子 请求百度

      OkHttpClient client = new OkHttpClient();
      HttpUrl httpUrl = HttpUrl.parse("www/baidu.com").newBuilder()
      .addQueryParameter("city","beijing")
      .build();
      Request request = new Request.Builder()
      .url(httpUrl)
      .build();

      Response response = client.newCall(request).execute();

    
    2.  异步POST请求 FormBody

      OkHttpClient client = new OkHttpClient();
      FormBody body = new FormBody.Builder()
        .add("name","xiaoming")
        .add("age","18")
        .build();
      Request request = new Request.Builder()
        .url("www/baidu.com")
        .post(body)
        .build();
      Response response = client.newCall(request).execute();

  3. 异步上传文件 MultipartBody

  MediaType MEDIA_TYPE = MediaType.parse("text/x-markdown; charset=utf-8");
  String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/nihao.txt";
  File file = new File(path);
  RequestBody requestBody = RequestBody.create(file,MEDIA_TYPE);
  MultipartBody body = new MultipartBody.Builder()
      ----->上传字符时候需要加上setType特殊类型,否则无法上传成功
.addFormDataPart("filename", "filename", requestBody)
.build();
  OkHttpClient client = new OkHttpClient();
  Request request = new Request.Builder()
.url("www.baidu.com")
.post(body)
.build();

 4.异步下载文件
  String url = "https://img-my.csdn.net/uploads/201603/26/1458988468_5804.jpg";
  final Request request = new Request.Builder().url(url).build();
  Call call = mOkHttpClient.newCall(request);
  call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: 失败");
}

@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream is = response.body().byteStream();
String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/shu.jpg";
File file = new File(path);
FileOutputStream fos = new FileOutputStream(file);
try{
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer)) != -1) {
fos.write(buffer,0,len);
}
fos.flush(); //文件的读写,这个需要多看看和学习
}catch (Exception e){
e.printStackTrace();
}
Log.d(TAG, "onResponse: --->下载完成");
}
});

  二、同步和异步的区别

   里面有个Dispatcher这个类来实现,它主要作用是维护请求的状态(同步和异步),并且维护一个线程池,用于执行请求

   同步请求

   同步请求发送请求之后,就会进入阻塞状态,Dispatcher(分发器)主要做两个事情:保存同步请求、移除同步请求,直到收到响应。   

   异步请求

   异步请求放到线程池里面,Dispatcher类主要做三件事情:正在执行异步队列、等待执行异步队列、维护一个还有一个线程池

   里面之所以有两个异步请求队列:当前运行的异步队列小于64时候,它就会被放入到正在运行的异步队列(runningAsyncCalls)中,然后去运行线程池,否则就是加入就绪缓冲队列(readyAsyncCalls)当中作为等待

  

  三、缓存的原理以及实现

   1.缓存原理:

    

   2.缓存相关的字段

    Expirse : 缓存失效的时间

    Cactce-Contral :  控制缓存  缓存类型

      private :      客户端可以去缓存

      public   :      客户端和代理服务器都可以缓存

 

      max-age  :   表示多少秒后失效(在服务端用的较多)

 

·      no-cache  : 通过服务验证码(304)是否能使用缓存

 

      no-store   :  代理和本地都不可以使用缓存,只能从服务器去拿数据

 

    Last-Modified :  最后一次修改时间(比如只是添加一个空格,时间就不一样,所以就出现ETag这个关键字段)

    ETag :   通过返回的Response返回数据比较里面两个内容是否一直

    If-Modified-Since :  与Last-Modified成对存在的

    If-None-Match :   与ETag成对存在的

   3.缓存的机制

    int maxSize = 10 * 1024 * 1024;
    Cache cache = new Cache(new File("sd"), maxSize);
    OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();
    Request request = new Request.Builder()
      .url("http://www.qq.com")
      .build();
    Response response = client.newCall(request).execute();
    String string = response.body().toString();     --------->如果你不去读取返回的Response的请求体,

                           下次在请求也还是网络请求,并不是缓存请求
    if(response.isSuccessful()){
    Log.i(TAG, "run: = " + response.networkResponse().toString());
    Log.i(TAG, "run: = " + response.cacheResponse().toString());
    Log.i(TAG, "run-------------------------------");
    Response response1 = client.newCall(request).execute();
    String string = response1.body().toString();   ------>这次再次请求就是缓存请求
    if(response1.isSuccessful()){
    Log.i(TAG, "run: = " + response1.networkResponse().toString());
    Log.i(TAG, "run: = " + response1.cacheResponse().toString());

  4. 缓存实现

    

    CacheInterceptor : 缓存拦截器

    CasheStrategy : 缓存策略(是用本地缓存还是网络缓存),networkResponse为空的时候执行cacheResponse,否则需要取网络请求

    Cache : 缓存目录,这里面就有put  get remove等方法进行对缓存的操控

  四、多线程下载功能

    1.关键的字段  

     Transer-Encoding : chunked  :  无法拿到整个文件的长度

     content-length :   访问文件的总长度的大小

     Range :   可以访问服务器某一个字段的长度大小

    2. 下载文件遇到的问题

      文件存储的路径 :  检查是否有SD卡的路径

      文件是否受损 : 通过拿到服务器的文件的MD5,然后去和你本地的MD5做对比观察是否相等,如果不相等说明文件已经受损

     文件空间的大小 :  下载文件是否比剩余空间小,做一个判断

     进度条的更新 :   

     数据的保存 :  

   五、Https使用

    1.https加密的常见知识

      对称加密: 秘钥是相同

      非对称加密: 一个是公钥,一个是私钥,公钥只能用私钥去解,私钥只能用公钥去解

      数字证书: 

    2.SSL/TLS的运行机制 :

      a.客户端会告诉服务端证书(公钥)、数据加密算法、以及生成一个随机数

      b.服务端接受之后对证书进行私钥解密,验证是否可信,如果成功,服务端会确认是使用加密算法、以及生成一个随机数给客户端

      c.客户端再对服务端返回数据进行验证,验证通过之后就发送对称加密对数据进行加密处理,发送给服务端

      d.服务端就会对称加密进行解析拿到数据

      证书采用的是非对称加密,而数据传输采用的是对称加密

    3.DNS讲解 :  域名解析

    比如我去直接访问IP地址,它会抛出校验抛出的异常,connect请求连接时候添加HostnameVerifier这个接口里面的verify,直接返回为true,就可以跳过校验

    class MyHostVerify  implements HostnameVerifier() {

    @Override

    public boolean verify(){

      手动可以去写校验方法

      return true;

    }

  }

  六、自定义拦截器

   1.重写Interceptor这个类

    public interface Interceptor {
      Response intercept(Chain chain) throws IOException;
      interface Chain {
        Request request();
        Response proceed(Request request) throws IOException;
        Connection connection();
      }
     }

    /**
     * 重试拦截器
   */
  
 public class RetryIntercepter implements Interceptor {
    public int maxRetry;//最大重试次数
    private int retryNum = 0;//假如设置为3次重试的话,则最大可能请求4次(默认1次+3次重试)
    public RetryIntercepter(int maxRetry) {
      this.maxRetry = maxRetry;
    }
    @Override
    public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    System.out.println("retryNum=" + retryNum);
     Response response = chain.proceed(request);
    while (!response.isSuccessful() && retryNum < maxRetry) {
      retryNum++;
       System.out.println("retryNum=" + retryNum);
       response = chain.proceed(request);
    }
    return response;
    }
   }

  2.添加自定义拦截器

   mClient=new OkHttpClient.Builder()
      .addInterceptor(new RetryIntercepter(3))//重试
      .addInterceptor(logging)//网络日志
      .addInterceptor(new TestInterceptor())//模拟网络请求
      .build();  

  3.addInterceptor(添加应用拦截器)和addNetworkInterceptor()的区别

   

      addInterceptor :  总是只调用一次,即使HTTP响应是从缓存中获取,不是从网络获取的

      addNetworkInterceptor : 能够操作中间过程的响应,可以观察网络上传的数据

-------------------------------------------------------------------------------------------------------------------------------------------

 

 

一、StingUtils

二、Glide

三、ButterKnife

四、Indicator

五、MasterDesign使用

六、OkHttp

  // okhttp,sniffer packet--->适用于测试人员抓包
  debugCompile 'com.readystatesoftware.chuck:library:1.1.0'
  releaseCompile 'com.readystatesoftware.chuck:library-no-op:1.1.0'

//okhttp,chrome sniffer packet---->适用于开发人员抓包
implementation 'com.facebook.stetho:stetho:1.5.0'
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.0'


七、DrawerLayout的学习


八、BaseTitleActivity学习以及XML文件学习

九、EventBus的使用


十、AppBarLayout -----> app:layout_scrollFlags="scroll"
  MagicIndicator indicator MagicIndicator

十一、Palette

十二、 这两个区别
//这里一定要调用childFragmentManager
adapter = new MusicUIAdapter(getActivity(),
getFragmentManager());
adapter = new MusicUIAdapter(getActivity(), getChildFragmentManager());

十三、CardView框架



十四、 RecommentFragment
    adapterWrapper = new LRecyclerViewAdapter(adapter);
adapterWrapper.setSpanSizeLookup(new LRecyclerViewAdapter.SpanSizeLookup() {
@Override
public int getSpanSize(GridLayoutManager gridLayoutManager, int position) {
// 先获取ItemType
int itemViewType = adapterWrapper.getItemViewType(position);
if (position<adapterWrapper.getHeaderViewsCount() || position>(adapterWrapper.getHeaderViewsCount()+adapter.getItemCount())) {
// f当前位置的Itemheader,占用列数spanCount一样
return ((GridLayoutManager) layoutManager).getSpanCount();
}
return adapter.setSpanSizeLookup(position);
}
});




getSupportActionBar().setDisplayHomeAsUpEnabled(true);
 

RequestOptions需要学习

 

posted on 2019-10-05 15:35  zhang11111wei  阅读(366)  评论(0编辑  收藏  举报

导航