Sparky


  • 首页

  • 归档

未命名

发表于 2019-05-06

制作jar包sdk

  1. 创建library项目或者设置原来项目为library.

    apply plugin: 'com.android.library'
    
  2. 编写sdk代码.
  3. 再项目build.gradle里添加gradle task

    task deleteOldJar(type:Delete){
        delete('build/libs/EinkUpdateHelper.jar')
    }
    
    task exportJar(type:Copy){
        from('build/intermediates/bundles/release/')
        into('build/libs/')
        include('classes.jar')
        rename('classes.jar', 'EinkUpdateHelper.jar')
    }
    
    exportJar.dependsOn(deleteOldJar,build)
    
  4. 执行gradle task,在as右侧gradle标签卡,选择exportJar或者手动添加task.

未命名

发表于 2019-05-06

线程同步

线程同步的三种方式

  • 锁(synchronized,rentrantlock)
  • 可见性(volatile,atomic)
  • 变量私有化(threadlocal)

线程同步的方式

synchronized关键字

互斥锁机制,类锁和对象锁

ReentraintLock类

mLock.lock()

mLock.unLock()

volatile关键字

当我们声明volatile关键字实际上包括两层含义:

  1. 禁止进行指令重排序
  2. 当一个线程修改了某个变量的值,这个新值对其他线程立即可见

volatile关键字并不一定能够保证线程同步,需要满足下边的条件:

  1. 对变量的写操作不依赖当前值
  2. 该变量没有包含在其他变量的不变式中

上边的条件可以理解为volatile修饰的这个对象是原子性的才能保证线程同步

atomic原子类

本地变量ThreadLocal

未命名

发表于 2019-05-06

我想学的一本书

别人给我总结系列

未命名

发表于 2019-05-06

值得收藏的博客

Android

源码分析类

技术分析类

高能实现类

第三方用法类

Java

源码分析

知识点总结

常见知识点

网络编程

IO

HTTP/HTTPS

学习方法和工具

算法和数据结构

设计模式

未命名

发表于 2019-05-06

如何阅读源码

抽丝剥茧,点到为止

  1. 认准一个功能点
  2. 分析这个功能是如何实现的(主要是追寻主体的实现逻辑,不需要搞懂每一行代码的意思)

未命名

发表于 2019-05-06

java

  • string stringbuilder stringbuffer的区别
  • 多线程同步多种方式
  • java线程

    android

  • asynctask 源码解析Android中AsyncTask的工作原理 或者 Android AsyncTask完全解析,带你从源码的角度彻底理解
  • http和https区别
  • Glide加载图片的原理
  • okhttp实现原理
  • Android线程间通信机制
  • viewpager加载
  • Android异步消息处理机制完全解析 带你从源码的角度彻底理解

未命名

发表于 2019-05-06

SQlite数据类型

SQLite 存储类【存储类型】

TEXT

值为文本字符串,使用数据库编码存储

BLOB

值是一个blob数据,完全根据他的输入存储

INTEGER

值是一个带符号的整数,根据值得大小存储在1,2,4,6,8字节中

REAL

值是一个浮点数,存储为8字节IEEE浮点数字

NULL

值是一个NULL值

SQLite亲和类型,当数据插入时,会首先采用亲和类型作为该值的存储方式

TEXT(如果类型字符串包括CHAR,CLOB,TEXT,那么字段的亲缘类型为TEXT)
  • CHARACTER(20)
  • VARCHAR(255)
  • VARYING CHARACTER(255)
  • NCHAR(55)
  • NATIVE CHARACTER(70)
  • NVARCHAR(100)
  • TEXT
  • CLOB
    INTEGER(如果类型字符串包含INT,那么字段的亲缘类型为INTEGER)
  • INT
  • INTEGER, 32位
  • TINYINT
  • SMALLINT, 16位
  • MEDIUMINT
  • BIGINT
  • UNSIGNED BIG INT
  • INT2
  • INT8
    NUMBERIC(其他的亲缘类型都为NUMBERIC)
  • NUMBERIC
  • DECIMAL(p.s) 精确值p是指全部由几个数的大小值,s是指小数点后有几位数。默认p=5,s=0
  • BOOLEAN
  • DATE
  • DATETIME, 必须写成’2010-08-05’不能写为’2010-8-5’
    NONE(如果类型字符串包含BLOB,那么字段的亲缘类型是NONE)
  • BLOB
  • no datatype specified
    REAL(如果类型字符串中包括DOUB,FLOA,REAL,那么字段亲缘类型是REAL)
  • REAL
  • DOUBLE
  • DOUBLE PRECOSION
  • FLOAT

Rxjava

发表于 2019-05-06

RxJava

简介

RxJava是RectiveX的java VM实现,用来使用可观察序列来编写异步和基于事件的程序的库。

主要是用来实现异步任务,和事件总线的功能

使用

  1. 创建观察者,有两种实现方式

    1. 创建Observer

      Observer<String> observer = new Observer<String>() {
          @Override
          public void onSubscribe(Disposable d) {
              Log.i(TAG, "onSubscribe: ");
          }
      
          @Override
          public void onNext(String s) {
              Log.i(TAG, "onNext: ");
          }
      
          @Override
          public void onError(Throwable e) {
              Log.i(TAG, "onError: ");
          }
      
          @Override
          public void onComplete() {
              Log.i(TAG, "onComplete: ");
          }
      };
      
    2. 创建Subscriber

      Subscriber subscriber = new Subscriber() {
          @Override
          public void onSubscribe(Subscription s) {
              Log.i(TAG, "onSubscribe: ");
          }
      
          @Override
          public void onNext(Object o) {
              Log.i(TAG, "onNext: ");
          }
      
          @Override
          public void onError(Throwable t) {
              Log.i(TAG, "onError: ");
          }
      
          @Override
          public void onComplete() {
              Log.i(TAG, "onComplete: ");
          }
          };
      
  2. 创建被观察者,有三种实现方式

    1. Observable.create
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                // 使用该方法创建observable,需要手动调用onNext, onError, onComplete方法,而onSubscribe是自动调用的
                e.onNext("observable.create");
            }
        }).subscribe(observer);
2. Observable.just


         // 使用该方法创建observable,会自动调用onSubscribe,onNext,onError,onComplete
        Observable.just("observable.just").subscribe(observer);
3. Observable.fromArray


        // 使用该方法创建的observable,会自动调用onSubscribe,onNext,onError,onComplete
        String[] quotations = {"observable.fromArray"};
        Observable.fromArray(quotations).subscribe(observer);
  1. 创建被观察之后,通过subscribe方法关联观察者

    observable.subscribe(observer)

  2. 观察者的方法

    onError: 表示事件队列异常,队列终止,下一步会回调onComplete

    onSubscribe: 当观察者订阅被观察者的时候,会回调该方法

    onNext: 普通事件,可以在该方法中做一些业务逻辑

    onComplete: 表示事件队列完结

  3. 操作符,包括普通操作符,变换操作符,过滤操作符,组合操作符,辅助操作符,辅助处理操作符,条件操作符,布尔操作符,转换操作符

  1. 普通操作符,例如,interval,intervalRange
 // 普通操作符
// 用于周期执行
Observable.interval(3, TimeUnit.SECONDS).just("observable.interval").subscribe(observer);

// 用于延迟执行并且定期执行
Observable.intervalRange(0, 6, 0, 3, TimeUnit.SECONDS).create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> e) throws Exception {
        Log.i(TAG, "subscribe: ");
    }
}).subscribe(observer);
  1. 变换操作符,例如,map,flatmap,cast,concatmap
// 变换操作符
// map,指定一个Function对象,将一个Observable转换成另一个Observable对象。
Observable.just("observable.map").map(new Function<String, String>() {
    @Override
    public String apply(String s) throws Exception {
        return s + "[map]";
    }
}).subscribe(observer);

// flatmap,将一个observable对象转换成另一个observable集合,然后将这些observable对象发射的数据平坦的放进一个单独的observable。
Student[] students = {};
Observable.fromArray(students).flatMap(new Function<Student, ObservableSource<String>>() {
    @Override
    public ObservableSource<String> apply(Student student) throws Exception {
        return Observable.fromArray(student.classes);
    }
}).subscribe(observer);

// cast负责将observable中的所有数据转换成指定类型
Student[] stus = {};
Observable.fromArray(stus).flatMap(new Function<Student, ObservableSource<?>>() {
    @Override
    public ObservableSource<?> apply(Student student) throws Exception {
        return null;
    }
}).cast(String.class).subscribe(observer);
  1. 过滤操作符,包括,skip,take,element,fileter等
// 过滤操作符
// filter,对Observable产生的结果自定义规则进行过滤,只有满足条件的结果才提交给订阅者。
Observable.just("你好", "中国", "世界").filter(new Predicate<String>() {
    @Override
    public boolean test(String s) throws Exception {
        return s.equals("你好");
    }
}).subscribe(new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(String s) {

    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
});

// skip,过滤掉前n项
Observable.range(0,10).skip(2).subscribe(new Observer<Integer>() {
    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(Integer integer) {
        Log.i(TAG, "onNext: " + integer);
    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
});

// take, 取前n项
Observable.range(0, 10).take(5).subscribe(new Observer<Integer>() {
    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(Integer integer) {
        Log.i(TAG, "onNext: " + integer);
    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
});

// throttleWithTimeout:如果在限定的时间内,源Observable有新的数据发射出来,该数据就会被丢弃,同时throttleWithTimeout重新开始计时,如果每次都是在计时结束前发射数据,那么这个限流就会走向极端(只会发射最后一个数据)
Observable.just("hell", "o," "worl", "d").throttleWithTimeout(200, TimeUnit.MILLISECONDS).subscribe(observer);


// ditinct, 去重
Observable.just("hh", "hh", "hhh", "h").distinct().subscribe(new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(String s) {
        Log.i(TAG, "onNext: " + s);
    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
});
  1. 组合操作符, merge,startWidth,concat,jion,switch,zip
// 组合操作符
// merge将多个observable合并到一个observable中进行发射
Observable<String> observable1 = Observable.just("1", "2");
Observable<String> observable2 = Observable.just("3", "4");
Observable.merge(observable1, observable2).subscribe(observer);

// concat将多个observable合并并按队列顺序发射,前一个没发射完无法进行下一个发射
Observable.concat(observable1, observable2).subscribe(observer);

// zip, 合并两个或者多个Obserable发射出的数据项,根据指定的函数变换它们,并发射一个新值。    
  1. 辅助操作符,DO、delay、observeOn、timeout、timeInterval、timestamp、subscribeOn、meterialize和to等。
// delay:延迟执行发射数据
Observable<String> observable1 = Observable.just("你好", "hello World");
Observable<String> observable2 = Observable.just("new obj", "mergeobj");
Observable.concat(observable1, observable2).delay(5, TimeUnit.SECONDS).subscribe(observer);

// subscribeOn:指定Obserable自身在那个线程上运行。
// observeOn:指定Obserable发射出的数据在那个线程运行。
  1. 错误操作符,包括catch和retry

    catch能够拦截原始Observable的onError通知,将它替换为其他数据项或者数据序列,让产生的Observable能够正常终止或者根本不终止。

    catch实现分为三个不同的操作符:

    1、onErrorReturn:返回原有Observable行为的备用Observable, 备用的Observable忽略原有的Observable的onError调用,即不会将错误传递给观察者,而是发射一个特殊的项,以及调用观察者的onCompleted。

    2、onErrorResumeNext:跟onErrorReturn一样返回备用的Observable,不会调用原有的Observable的onError,它会发射备用的Observable数据。

    3、onExceptionResumeNext:如果onError收到的Throwable不是一个Exception,它会将错误传递给观察者的onError方法,不会使用备用的Observable。

    retry:不会将原有的Observable的onError通知传递给观察者,这会订阅这个Observable,再给它一次机会无错误地完成其数据序列,而它总会传递onNext通知给观察者。该操作符有可能造成数据重复,因为重新订阅。如果超过了重新订阅的次数,就不会再次订阅了,而是把最新的一个onError通知传递给观察者。

  2. 条件操作符,包括:defaultEmpty、skipUntil、amb、skipWhile、takeUtil、takeWhile

defaultEmpty:如果原有的Observable没有发射数据,就发射一个默认的数据。

skipUntil:订阅原始的Observable,但是忽略它的发射物,直到第二个Observable发射了一项数据那一刻,它开始发射原始Observable。
  1. 布尔操作符,包括:all、isEmpty、contains、exists和sequenceEqual。

    关于条件操作符和布尔操作符,读者可以关注《RxJava操作符(08-条件和布尔操作) 》这篇文章,文章地址:

  2. 转换操作符,转换操作符能够将Observable转换为另一个对象或者数据结构,其中转换操作符包括:toMap、toMultiMap、toList、toSortedList、nest和getIterator等。

    // toMap:将原始的Observable发射的所有数据项集合到一个Map中,然后发射该Map。
    String s1 = "你好";
    String s2 = "hello world";
    String s3 = "lalala";
    
    Observable.just(s1,s2,s3).toMap(new Function<String, String>() {
        @Override
        public String apply(@NonNull String s) throws Exception {
            return s;
        }
    }).subscribe(new SingleObserver<Map<String, String>>() {
        @Override
        public void onSubscribe(@NonNull Disposable d) {
    
        }
    
        @Override
        public void onSuccess(@NonNull Map<String, String> stringStringMap) {
            Log.i("test",""+stringStringMap);
        }
    
        @Override
        public void onError(@NonNull Throwable e) {
    
        }
    });
    
    // toMultiMap:类似于toMap,不同的地方在于map的value是一个集合。
    
    // toList:将发射的数据组成一个List。
    String s1 = "你好";
    String s2 = "hello world";
    String s3 = "lalala";
    
    Observable.just(s1,s2,s3).toList().subscribe(new SingleObserver<List<String>>() {
        @Override
        public void onSubscribe(@NonNull Disposable d) {
    
        }
    
        @Override
        public void onSuccess(@NonNull List<String> strings) {
            Log.i("test",""+strings);
        }
    
        @Override
        public void onError(@NonNull Throwable e) {
    
        }
    });
    

    关于其他操作符,读者可以参考《RxJava操作符大全》这篇文章。

  3. buffer操作符

// buffer操作符能收集多个结果到列表中,订阅后会自动清空结果,也可以周期性收集结果
Observable.range(0, 5).buffer(2).subscribe(new Observer<List<Integer>>() {
    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(List<Integer> integers) {
        Log.i(TAG, "onNext: " + integers);
    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
});

Observable.just("你好", "中国", "我爱", "我家").buffer(3).subscribe(new Observer<List<String>>() {
    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(List<String> strings) {
        Log.i(TAG, "onNext: " + strings);
    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
});
  1. 线程调度

    前面讲解辅助操作符的时候,我们知道使用subscribeOn可以指定Obserable自身在那个线程上运行。使用observeOn可以指定Obserable发射出的数据在那个线程运行。RxJava默认线程是在调用subcribe方法的线程上进行回调,但是如果想切换线程,就需要使用Scheduler。

    在RxJava中内置了以下几个Scheduler:

    1、Scheduler.immediate():运行在当前线程,是timeout、timestamp和timeInterval操作符的默认调度器。

    2、Scheduler.io():I/O操作使用的Scheduler。

    3、Scheduler.newThread():开启一个新的线程执行操作。

    2和3的区别就是:2的内部实现了一个无数量上限的线程池,重用空闲的线程,因此2具有更高的效率

    4、Scheduler.trampoline():可以将任务通过trampoline方法加入队列,该调度器会按顺序处理队列的任务,是repeat和retry操作符的默认调度器。

    5、Scheduler.computation():计算所使用的调度器,它具有固定的线程池,大小为cpu核数,注意不要将io操作放到computation中,否则io操作的等待时间会浪费cpu。该调度器是buffer、delay、sample、debounce、interval和skip的默认调度器。

    6、AndroidSchedulers.mainThread():表示在主线程中运行,该调度器是RxAndroid提供的。

    Observable.just("你好","hello world")
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer);
    

未命名

发表于 2019-05-06

java并发编程实战

1. 多线程简介

2. 线程的安全性

判断一个对象是否需要线程安全,取决于它是否被多个线程访问。

需要做的是采用同步机制来协同对对象可变状态的访问。

当多个线程访问同一个状态变量并且有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变量的访问。

主要的同步机制是synchronized关键字,除此之外还有volatile类型的变量,显式锁,原子变量。

未命名

发表于 2019-05-06

java io

IO流图解

字节流和字符流的区别

  • 字节流操作的基本单元是字节,字符流操作的基本单元是Unicode码元
  • 字节流默认不适用缓冲区,字符流使用缓冲区
  • 字节流通畅用于处理二进制数据,实际上它可以处理任意类型的数据,但他不支持直接读取和写入unicode码元,字符流通常处理文本数据,它支持写入以及读取Unicode码元
1234…10
Sparky

Sparky

我是谁?我在做什么?我为什么要这么做?我想做什么?我要怎么做?

99 日志
© 2019 Sparky
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4