安卓高效框架简单使用

来源:互联网 发布:手机能用淘宝助理吗 编辑:程序博客网 时间:2024/05/21 05:05

安卓高效框架

Rx系列

RxAndroid

本文使用的是RxAndroid 2.0.1,Rx2.xx和Rx1.xx有较大的区别,此处只讨论2.xx

Rx牛逼的异步响应式框架,这里只是个人的学习记录,可能有些地方有误,仅供参考。
如果想深入了解请移步到官网,或者是中文翻译的官网

学习地址:

https://gold.xitu.io/entry/5884374e570c350062c1ac3b

https://gank.io/post/560e15be2dca930e00da1083

Rx实现原理个人以为可简单理解为一个事件发出者和一个事件接收者,两者之间通过订阅建立联系,事件发出和事件接收处理都可以在不同的线程,框架默认是在主线程中做所有的事,所以如果有耗时任务,请务必使用相应的线程切换方法进行切换。

框架原理

配置Rx2.0:

compile ‘io.reactivex.rxjava2:rxandroid:2.0.1’

如果要使用retrofit网络加载框架,则需添加以下依赖:

compile ‘com.squareup.retrofit2:retrofit:2.1.0’

compile ‘com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0’

compile ‘com.squareup.retrofit2:converter-gson:2.0.1’

使用RxAndroid:

Observable:

Observable的创建方法很多,列举如下:

  • Create — 常规创建方式,事件的产生需要自己实现(调用onNext)
  • Defer — 不会立即创建一个Observable,只有调用subscribe时才会创建,而且会为每一个订阅者创建一个新的Observable(事件可以被多个订阅者订阅)
  • Empty/Never/Throw — create Observables that have very precise and limited behavior,不知道搞什么的~
  • fromIterable — 从一个可以迭代的集合中产生事件
  • fromArray — 从一个数组中产生
  • Interval — 按一定的时间间隔发送相同事件
  • Just — 传递一个数值集合,可以是数组和集合或者多个单一元素
  • Range — 传递一个数值范围,然后框架会产生范围之间的所有数值
  • Repeat — 重复发送某个相同的事件
  • Start — create an Observable that emits the return value of a function
  • Timer — create an Observable that emits a single item after a given delay

常规使用:

//创建一个ObservableObservable.create(new ObservableOnSubscribe<Integer>()    {        //在该方法中产生事件,并调用Emitter发射事件        @Override        public void subscribe(ObservableEmitter<Integer> e) throws Exception        {            //一般使用onNext产生事件交给下游处理            e.onNext(1);            SystemClock.sleep(5000);            e.onNext(2);            SystemClock.sleep(5000);            e.onNext(3);            //此处的onComplete表示事件已经发送完成,下游不需要再处理了,应该在事件产生完成时调用一下onComplete            e.onComplete();        }    })    //订阅在io线程,意思是上面的subscribe的事件产生在哪个线程,subscribeOn一般只会调用一次    //newThread() 总是在新的线程中执行    //computation 主要用于CPU密集型任务    //io          主要用于网络访问,文件处理    //immediate() 在当前线程立即开始执行任务    .subscribeOn(Schedulers.io())    //观察在哪个线程,也不知道是不是这个意思           //observeOn可以随便切换,表示接下来的操作在observeOn设定的线程执行,切换线程的灵魂所在    .observeOn(AndroidSchedulers.mainThread())    .subscribe(new Observer<Integer>()    {        @Override        public void onSubscribe(Disposable d)        {            Toast.makeText(mContext, "开始", Toast.LENGTH_SHORT).show();        }        @Override        public void onNext(Integer value)        {            tv.setText("" + value);        }        @Override        public void onError(Throwable e)        {        }        @Override        public void onComplete()        {            Toast.makeText(mContext, "完成", Toast.LENGTH_SHORT).show();        }    });    //subscribeOn会产生Disposable,这个Disposable是用于取消订阅事件,防止内存泄漏,    //使用该框架请注意在OnDestroy方法或者其他合适的方法中调用Disposable对象的    if(dis != null && (!dis.isDisposed()))    {        dis.dispose();    }

使用Flowable

Flowable(处理背压问题,observable不具备了,所谓背压就是当生产速度大于消费速度时的一种处理策略,比如快速点击事件)

    Flowable<String> flow = Flowable.create(new FlowableOnSubscribe<String>()            {                @Override                public void subscribe(FlowableEmitter<String> e) throws Exception                {                    e.onNext("hello rx");                    e.onComplete();                }            }, BackpressureStrategy.BUFFER);            Subscriber<String> sub = new Subscriber<String>()            {                @Override                public void onSubscribe(Subscription s)                {                    Log.e("s", "订阅开始...");                    s.request(Long.MAX_VALUE);                }                @Override                public void onNext(String s)                {                    Toast.makeText(RxActivity.this, s, Toast.LENGTH_SHORT).show();                }                @Override                public void onError(Throwable t)                {                    Toast.makeText(RxActivity.this, "error", Toast.LENGTH_SHORT).show();                }                @Override                public void onComplete()                {                    Toast.makeText(RxActivity.this, "完成", Toast.LENGTH_SHORT).show();                }            };            flow.subscribe(sub);

使用Subject

Subject既可以发事件又可以处理事件

Subject subject = PublishSubject.create();subject.observeOn(EventThread.getScheduler(thread))       .subscribe(o -> {         try {               if (valid) {                  handleEvent(o);                }             } catch (InvocationTargetException e) {               throwRuntimeException("Could not dispatch event: " +               o.getClass() + " to subscriber " + SubscriberEvent.this, e);             }});

RxBus

github:https://github.com/AndroidKnife/RxBus
注意该项目是使用的RxJava1.xx,如果项目中使用RxJava2.xx会出现Rx版本冲突而无法通过编译,个人解决方法是复制了RxBus的代码到项目中,再稍作修改。注意: 如果复制修改了别人的开源代码,请添加开源许可。

RxBus其实是通过RxJava实现的,其作用跟EventBus一样,能够在各种情形下进行数据交换,而无需繁复的代码调用,只需要在两个需要交换数据的地方注册就可以了。

使用方法

首先注册@Overrideprotected void onCreate(Bundle savedInstanceState){    super.onCreate(savedInstanceState);    setContentView(R.layout.main_activity);    //注册    RxBus.get().register(this);}@Overrideprotected void onDestroy(){    super.onDestroy();    //取消注册,防止内存泄漏    RxBus.get().unregister(this);}//在响应activity或fragment中添加某个方法,如:@Subscribepublic void eat(String food) {    // purpose}//或者这样的//thread指定响应线程,如果是ui操作,需要选择MAIN_THREAD,或者默认不写,//tags是标签,用于事件之间进行区分,如果事件不多,tags不写即可,框架会有默认值。//此处是个数组,可以同时响应多种事件,如果要单独处理,需要分开写。@Subscribe(thread = EventThread.IO,tags = {@Tag(BusAction.EAT_MORE)})public void doSomething(List<String> foods) {    // purpose}//订阅以后在其他的activity或者fragment中使用post//带tags,只有订阅时tags里面有"dd"才会响应RxBus.get().post("dd", "走你");//默认RxBus.get().post("走你");

Retrofit

square出品,Rx风格的网络请求框架,注解式的请求方式,底层使用OkHttp,稳定性不用怀疑,必是良品。在访问一个链接得到一个结果,然后由结果去访问另外一个链接的这种情形下尤其有用。

使用Retrofit需要以下依赖:

compile ‘com.squareup.retrofit2:retrofit:2.1.0’

compile ‘com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0’

compile ‘com.squareup.retrofit2:converter-gson:2.0.1’

使用方法如下,由于没有对Retrofit太多的研究,如果要深入了解可移步官网或者
http://www.jianshu.com/p/308f3c54abdd

Retrofit retrofit = new Retrofit.Builder()            //Retrofit建议此处放app后台的公共地址,并带斜杠            .baseUrl("http://192.254.1.5:8080/HotMusic/")            //此处就是和RxJava连接的关键            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())            //此处是Retrofit解析json需要使用的转换器            .addConverterFactory(GsonConverterFactory.create())            .build();    ApiService ser = retrofit.create(ApiService.class);    Call<User> call = ser.getUser();    call.enqueue(new Callback<User>()    {        @Override        public void onResponse(Call<User> call, Response<User> response)        {            Log.e("s", response.body().name);        }        @Override        public void onFailure(Call<User> call, Throwable t)        {        }    });}//public interface ApiService{    @GET("hot/getUser/{id}") //这里的{id} 表示是一个变量    Call<User> getUser(/** 这里的id表示的是上面的{id} */@Path("id") int id);}

Green Dao

greenDao是一个将对象映射到SQLite数据库中的轻量且快速的ORM解决方案。关于greenDAO的概念可以看官网

学习地址:http://www.jianshu.com/p/dac3bd9bad72

配置:

Project中的build.gradle中添加以下内容:

repositories {    jcenter()    mavenCentral()}dependencies {    classpath 'com.android.tools.build:gradle:2.2.3'    //lambda的配置    classpath 'me.tatarka:gradle-retrolambda:3.2.5'   //green dao的配置    classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'}

app中的build.gradle中添加以下内容:
//Green Dao的配置
使用插件
apply plugin: ‘org.greenrobot.greendao’
//添加依赖
compile ‘org.greenrobot:greendao:3.2.0’

//数据库配置,会自动在gen包下生成响应的类greendao {    schemaVersion 1    daoPackage 'com.white.hot.hotmusic.gen'    targetGenDir 'src/main/java'}

- schemaVersion 对应当前数据库版本
- daoPackage 由GreenDao自动生成代码所在的包名,默认的是在项目包下面新建一个gen。
- targetGenDir 设置自动生成代码的目录。

写好bean类,注意id必须为long型,然后点一下build就会自动生成DaoMaster,DaoSession,xxDao等类

  • @Property 标识该属性在表中对应的列名称,默认会都会存储到数据库,可以不写这个注解,使用@Property(nameInDb = “fnam”)自定义存储时的字段名,外键不能使用该属性
  • @Transient 标识该属性将不会映射到表中
  • @Entity:告诉GreenDao该对象为实体,只有被@Entity注释的Bean类才能被dao类操作,表名默认是实体类的名称
  • @Id:对象的Id,使用Long类型作为EntityId,否则会报错。(autoincrement = true)表示主键会自增,如果false就会使用旧值
  • @NotNull:属性不能为空
  • @Unique:该属性值必须在数据库中是唯一值
  • @Generated:编译后自动生成的构造函数、方法等的注释,提示构造函数、方法等不能被修改

注释帮助文档

使用本地数据库:

注意:由于green dao的内部机制,所有表的id都是 _id ,所有字段名都是大写,所以如果要使用raw中的数据库,则表的设计请遵循该原则。

常规用法

创建一个管理类

public class GreenDaoManager{    private static GreenDaoManager instance;    private DaoMaster mDaoMaster;    private DaoSession mDaoSession;    private static WeakReference<Context> wrContext;    private String dbName;    private GreenDaoManager(Context context, String dbName)    {        wrContext = new WeakReference<Context>(context);        this.dbName = dbName;        init();    }    public static GreenDaoManager getInstance(Context context, String dbName)    {        if(instance == null)        {            synchronized (GreenDaoManager.class)            {                if(instance == null)                {                    instance = new GreenDaoManager(context,dbName);                }            }        }        return instance;    }    private void init()    {        //字符串是数据库的名字        CustomDevOpenHelper helper = new CustomDevOpenHelper(wrContext.get(), dbName);        mDaoMaster = new DaoMaster(helper.getWritableDatabase());        mDaoSession = mDaoMaster.newSession();    }    public DaoMaster getDaoMaster()    {        return mDaoMaster;    }    public DaoSession getDaoSession()    {        return mDaoSession;    }    public DaoSession getNewSession()    {        mDaoSession = mDaoMaster.newSession();        return mDaoSession;    }}在其他地方使用GreenDaoManager.getInstance(this, "dbName").getDaoSession().getUserDao().save(user);详细增删该查自行百度~

使用本地数据库的管理类:

以下关于greendao读取raw中数据库的内容参考了:http://www.cnblogs.com/libertycode/p/6256000.html

public class LocalGDManager{    private static LocalGDManager instance;    private DaoMaster mDaoMaster;    private DaoSession mDaoSession;    private String dbName;    private static WeakReference<Context> wrContext;    private LocalGDManager(Context context,String dbName)    {        wrContext = new WeakReference<Context>(context);        this.dbName = dbName;        init();    }    public static LocalGDManager getInstance(Context context, String dbName)    {        if(instance == null)        {            synchronized (LocalGDManager.class)            {                if(instance == null)                {                    instance = new LocalGDManager(context, dbName);                }            }        }        return instance;    }    private void init()    {     //字符串是数据库的名字    //此处是自定义的Helper,因为自动生成的helper会强制生成所有表,对于我们从本地复制过去的表再对它进行创建肯定会出错     CustomDevOpenHelper devOpenHelper = new CustomDevOpenHelper(new GreenDaoContextWrapper(wrContext.get()),dbName, null);        mDaoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());        mDaoSession = mDaoMaster.newSession();    }    public DaoMaster getDaoMaster()    {        return mDaoMaster;    }    public DaoSession getDaoSession()    {        return mDaoSession;    }    public DaoSession getNewSession()    {        mDaoSession = mDaoMaster.newSession();        return mDaoSession;    }}

自定的helper,就是为了修改greendao的默认行为

public class CustomDevOpenHelper extends DaoMaster.DevOpenHelper{    @Override    public void onCreate(Database db)    {        DaoMaster.createAllTables(db, true);    }    @Override    public void onUpgrade(Database db, int oldVersion, int newVersion) {        Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");        DaoMaster.dropAllTables(db, false);        onCreate(db);    }    public CustomDevOpenHelper(Context context, String name)    {        super(context, name);    }    public CustomDevOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {        super(context, name, factory);    }}

需要自定义一个context wrapper用于复制本地数据库;

public class GreenDaoContextWrapper extends ContextWrapper{    private Context mContext;    private int dbRes;    public GreenDaoContextWrapper(Context base, int localDbRes)    {        super(base);        this.mContext = base;        dbRes = localDbRes;    }    @Override    public File getDatabasePath(String name)    {        String filePath = mContext.getDatabasePath(name).getAbsolutePath();        File file = new File(filePath);        if (!file.exists())        {            if(!file.getParentFile().exists())            {                file.getParentFile().mkdir();            }            buildDatabase(filePath);        }        return file;    }    /**     * 创建数据库文件,其实就是将raw文件夹下的数据库文件复制到应用的database文件夹下:     * /data/data/com.xxxx/databases/     *     * @param filePath     */    private void buildDatabase(String filePath)    {        Log.d("GreenDao", "buildDatabase");        InputStream inputStream = mContext.getResources().openRawResource(dbRes);        FileOutputStream fos = null;        try        {            fos = new FileOutputStream(filePath);            byte[] buffer = new byte[1024];            int length;            while ((length = inputStream.read(buffer)) > 0)            {                fos.write(buffer, 0, length);            }            fos.flush();            fos.close();            inputStream.close();        } catch (Exception e)        {            e.printStackTrace();        }    }    @Override    public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory)    {        Log.d("GreenDao", "openOrCreateDatabase");        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);        return result;    }    @Override    public SQLiteDatabase openOrCreateDatabase(String name, int mode,     SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler)    {        Log.d("GreenDao", "openOrCreateDatabase");        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);        return result;    }}

图片加载Glide

github:https://github.com/bumptech/glide

添加依赖:
compile ‘com.github.bumptech.glide:glide:3.7.0’

使用方法:

@Override public void onCreate(Bundle savedInstanceState) {  ...  ImageView imageView = (ImageView) findViewById(R.id.my_image_view);  Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);}// For a simple image list:@Override public View getView(int position, View recycled, ViewGroup container) {  final ImageView myImageView;  if (recycled == null) {    myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);  } else {    myImageView = (ImageView) recycled;  }  String url = myUrls.get(position);  Glide    .with(myFragment)    .load(url)    .centerCrop()    .placeholder(R.drawable.loading_spinner)    .crossFade()    .into(myImageView);  return myImageView;}

加载gif

Glide.with(this)            .load("http://wx2.sinaimg.cn/mw690/685d4d6cgy1fckkeajaovg20b407gb2b.gif")            .asGif()            .diskCacheStrategy(DiskCacheStrategy.SOURCE)            .into(vf);

View注解ButterKnife

@Bind(R.id.btnf)Button btnf;@OnClick(R.id.btnf)public void onClick(View v){    Toast.makeText(getContext(), "click fragment", Toast.LENGTH_SHORT).show();}

frament绑定

@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState){    View v = inflater.inflate(R.layout.frag, container);    ButterKnife.bind(this, v);    return v;}@Overridepublic void onDestroyView(){    super.onDestroyView();    ButterKnife.unbind(this);}

activity绑定:

@Overrideprotected void onCreate(Bundle savedInstanceState){    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    ButterKnife.bind(this);}@OnClick(R.id.btn)public void onClick(View v){    v.getId();    Toast.makeText(this, "click activity", Toast.LENGTH_SHORT).show();}

OkHttp3

square出品的网络加载框架,使用广泛,安卓系统内部已经集成了该框架。
关于使用,这里不重复了,网上资料相当多,这里我列出自己写的一个okhttp帮助类,由于资源模块暂时不能用,只能贴代码了:

参考了鸿洋大神的博客:http://blog.csdn.net/lmj623565791/article/details/47911083

使用这个类需要添加Gson的依赖:compile ‘com.google.code.gson:gson:2.2.4’

public class OkHttpManager    {        private static OkHttpManager mInstance;        private Handler mHandler;        private Gson mGson;        //默认超时时间20秒        private static int timeout = 20;        private OkHttpClient clientDefault;        private static Request simpleGetReq;        private static Request simplePostReq;        private static final String NET_FAILED_MSG = "未知异常!";        private static final String NET_FAILED_JSON_MSG = "Json 转换异常";        private static final String NET_FAILED_LINK_UNAVIlABLE_MSG = "无法连接";        private static final String NET_FAILED_TIMEOUT_MSG = "连接超时";        private static final String NET_FAILED_FILE_MSG = "文件不存在";        private OkHttpManager()        {            mGson = new Gson();            clientDefault = new OkHttpClient.Builder()                    .connectTimeout(timeout, TimeUnit.SECONDS)                    .readTimeout(timeout, TimeUnit.SECONDS)                    .retryOnConnectionFailure(true)                    .build();            mHandler = new Handler(Looper.getMainLooper());        }        public static OkHttpManager getInstance()        {            if (mInstance == null)            {                synchronized (OkHttpManager.class)                {                    if (mInstance == null)                    {                        mInstance = new OkHttpManager();                    }                }            }            return mInstance;        }        /***         * <b>发送一个get请求</b>, 回调要传入类型         *         * @param url      链接         * @param callback 回调函数         */        public void doGet(String url, final ResultCallback<? extends Object> callback)        {            if (callback == null)            {                throw new RuntimeException("回调不能为空");            }            if (simpleGetReq == null)            {                simpleGetReq = new Request.Builder().get().url(url).build();            } else            {                simpleGetReq = simpleGetReq.newBuilder().get().url(url).build();            }            deliveryRequest(simpleGetReq, callback);        }        /***         * <b>发送一个post请求</b>, 回调要传入类型         *         * @param url            链接         * @param callback       回调函数         * @param reqBodyParam  请求体参数         * @param reqHeader     请求头参数         */        public void doPost(String url, final ResultCallback<? extends Object> callback,                 Map<String, String> reqBodyParam, Map<String, String> reqHeader)        {            if (callback == null)            {                throw new RuntimeException("回调不能为空");            }            if (simplePostReq == null)            {                if(reqHeader == null)                {                    simplePostReq = new Request.Builder().post(reqBodyParam == null ?                     buildEmptyBody() :buildParams(reqBodyParam).build()).url(url).build();                }else                {                    //构造请求头                    Request.Builder builder = new Request.Builder();                    Set<String> set = reqHeader.keySet();                    for(Iterator<String> it = set.iterator();it.hasNext();)                    {                        String key = it.next();                        String value = reqHeader.get(key);                        builder.addHeader(key, value);                    }                    simplePostReq = builder.post(reqBodyParam == null ? buildEmptyBody() :                    buildParams(reqBodyParam).build()).url(url).build();                }            } else            {                if(reqHeader == null)                {                    simplePostReq = simplePostReq.newBuilder().post(reqBodyParam == null ?                     buildEmptyBody() :buildParams(reqBodyParam).build()).url(url).build();                }else                {                    //构造请求头                    Request.Builder builder = simplePostReq.newBuilder();                    Set<String> set = reqHeader.keySet();                    for(Iterator<String> it = set.iterator();it.hasNext();)                    {                        String key = it.next();                        String value = reqHeader.get(key);                        builder.addHeader(key, value);                    }                    simplePostReq = builder.post(reqBodyParam == null ? buildEmptyBody() :                        buildParams(reqBodyParam).build()).url(url).build();                }            }            deliveryRequest(simplePostReq, callback);        }        /***         * <b>发送一个post请求</b>, 回调要传入类型         *         * @param url            链接         * @param callback       回调函数         * @param reqBodyParam  请求体参数         */        public void doPost(String url, final ResultCallback<? extends Object> callback, Map<String, String> reqBodyParam)        {            doPost(url, callback, reqBodyParam, null);        }    //    public void doPost(String url, final ResultCallback<? extends Object> callback, Object obj)    //    {    //        Map<String, String> param = new HashMap<>();    //    }        /***         * <b>构建参数</b>         *         * @param map 参数         * @return         */        private FormBody.Builder buildParams(Map<String, String> map)        {            FormBody.Builder builder = new FormBody.Builder();            if (map != null && map.size() > 0)            {                Set<String> set = map.keySet();                for (Iterator<String> it = set.iterator(); it.hasNext(); )                {                    String key = it.next();                    String value = map.get(key);                    builder.add(key, value);                }            }            return builder;        }        private RequestBody buildEmptyBody()        {            return RequestBody.create(null, new byte[0]);        }        /***         * <b>传递请求</b>         *         * @param request         * @param callback         */        private void deliveryRequest(Request request, final ResultCallback callback)        {            clientDefault.newCall(request).enqueue(new Callback()            {                @Override                public void onFailure(Call call, final IOException e)                {                    failedResponse(e, callback);                }                @Override                public void onResponse(Call call, Response response) throws IOException                {                    try                    {                        final String string = response.body().string();                        if(string.startsWith("<html>") || string.startsWith("<HTML>"))                        {                            int errStartIndex = string.indexOf("<body>")+6;                            int errEndIndex = string.indexOf("</body>");                            String errStr = string.substring(errStartIndex, errEndIndex);                            errStartIndex = errStr.indexOf("<h1>")+4;                            errEndIndex = errStr.indexOf("</h1>");                            errStr = errStr.substring(errStartIndex, errEndIndex);                            failedResponse(new IllegalArgumentException(errStr), callback);                            return;                        }                        if (callback.mType == String.class)                        {                            successResponse(string, callback);                        } else                        {                            Object o = mGson.fromJson(string, callback.mType);                            successResponse(o, callback);                        }                    } catch (com.google.gson.JsonParseException e)//Json解析的错误                    {                        failedResponse(e, callback);                    } catch (IOException e)                    {                        failedResponse(e, callback);                    }                }            });        }        /***         * <b>下载, 如果要拿到进度,需要复写callback的<b>onProgress()</b>方法</b>, 回调方法要传入类型         *         * @param url              下载链接<br/>         * @param fileAbsolutePath 文件绝对路径<br/>         * @param callback         回调<br/>         */        public void download(final String url, final String fileAbsolutePath, final ResultCallback callback)        {            final Request request = new Request.Builder()                    .url(url)                    .build();            final DownloadProgressListener progressListener = new DownloadProgressListener()            {                @Override                public void update(long bytesRead, long contentLength, boolean done)                {                    onDownloadProgress(bytesRead, contentLength, done, callback);                }            };            clientDefault = clientDefault.newBuilder().addInterceptor(new Interceptor()            {                @Override                public Response intercept(Chain chain) throws IOException                {                    Response originalResponse = chain.proceed(chain.request());                    return originalResponse.newBuilder().body(                            new ProgressResponseBody(originalResponse.body(), progressListener))                            .build();                }            }).build();            final Call call = clientDefault.newCall(request);            call.enqueue(new Callback()            {                @Override                public void onFailure(Call call, final IOException e)                {                    failedResponse(e, callback);                }                @Override                public void onResponse(Call call, Response response) throws IOException                {                    InputStream is = null;                    byte[] buf = new byte[2048];                    int len = 0;                    FileOutputStream fos = null;                    try                    {                        is = response.body().byteStream();                        File file = new File(fileAbsolutePath);                        fos = new FileOutputStream(file);                        while ((len = is.read(buf)) != -1)                        {                            fos.write(buf, 0, len);                        }                        fos.flush();                        successResponse(file, callback);                    } catch (IOException e)                    {                        e.printStackTrace();                        failedResponse(e, callback);                    } finally                    {                        try                        {                            if (is != null) is.close();                        } catch (IOException e)                        {                        }                        try                        {                            if (fos != null) fos.close();                        } catch (IOException e)                        {                        }                    }                }            });        }        /***         * 文件上传         * @param url url         * @param fileAbsolutePath 文件绝对路径         * @param fileParamName 文件上传的参数名,相当于post的param         * @param callback 回调函数         */        public void upload(final String url, final String fileAbsolutePath, final String fileParamName,                         final ResultCallback callback)        {            if(callback == null)            {                throw new RuntimeException("回调不能为空");            }            File file = new File(fileAbsolutePath);            if(!file.exists())            {                failedResponse(new FileNotFoundException(), callback);                return;            }            final UploadProgressListener listener = new UploadProgressListener()            {                @Override                public void onRequestProgress(long bytesWrite, long contentLength, boolean done)                {                    onUploadProgress(bytesWrite, contentLength, done, callback);                }            };            String fileName = getFileName(fileAbsolutePath);            RequestBody reqBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);            MultipartBody mBody = new MultipartBody.Builder("--------------------------").setType(MultipartBody.FORM)                    .addFormDataPart(fileParamName , fileName , new ProgressRequestBody(reqBody, listener))                    .build();            clientDefault = clientDefault.newBuilder().build();            if (simplePostReq == null)            {                simplePostReq = new Request.Builder().post(mBody).url(url).build();            }else            {                simplePostReq = simplePostReq.newBuilder().url(url).post(mBody).build();            }            Call call = clientDefault.newCall(simplePostReq);            call.enqueue(new Callback()            {                @Override                public void onFailure(Call call, IOException e)                {                    failedResponse(e, callback);                }                @Override                public void onResponse(Call call, Response response) throws IOException                {                    try                    {                        final String string = response.body().string();                        if (callback.mType == String.class)                        {                            successResponse(string, callback);                        } else                        {                            Object o = mGson.fromJson(string, callback.mType);                            successResponse(o, callback);                        }                    } catch (com.google.gson.JsonParseException e)//Json解析的错误                    {                        failedResponse(e, callback);                    } catch (IOException e)                    {                        failedResponse(e, callback);                    }                }            });        }        public String getFileName(String filePath)        {            if (TextUtils.isEmpty(filePath))                return "";            return filePath.substring(filePath.lastIndexOf(File.separator) + 1);        }        /***         * 文件下载的响应体         */        private static class ProgressResponseBody extends ResponseBody        {            private final ResponseBody responseBody;            private final DownloadProgressListener progressListener;            private BufferedSource bufferedSource;            public ProgressResponseBody(ResponseBody responseBody, DownloadProgressListener progressListener)            {                this.responseBody = responseBody;                this.progressListener = progressListener;            }            @Override            public MediaType contentType()            {                return responseBody.contentType();            }            @Override            public long contentLength()            {                return responseBody.contentLength();            }            @Override            public BufferedSource source()            {                if (bufferedSource == null)                {                    bufferedSource = Okio.buffer(source(responseBody.source()));                }                return bufferedSource;            }            private Source source(Source source)            {                return new ForwardingSource(source)                {                    long totalBytesRead = 0L;                    @Override                    public long read(Buffer sink, long byteCount) throws IOException                    {                        long bytesRead = super.read(sink, byteCount);                        totalBytesRead += bytesRead != -1 ? bytesRead : 0;                        progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);                        return bytesRead;                    }                };            }        }        interface DownloadProgressListener        {            /**             * @param bytesRead     已下载字节数             * @param contentLength 总字节数             * @param done          是否下载完成             */            void update(long bytesRead, long contentLength, boolean done);        }        /***         * 文件上传的请求体         */        public  class ProgressRequestBody extends RequestBody        {            //实际的待包装请求体            private final RequestBody requestBody;            //进度回调接口            private final UploadProgressListener progressListener;            //包装完成的BufferedSink            private BufferedSink bufferedSink;            /**             * 构造函数,赋值             * @param requestBody 待包装的请求体             * @param progressListener 回调接口             */            public ProgressRequestBody(RequestBody requestBody, UploadProgressListener progressListener) {                this.requestBody = requestBody;                this.progressListener = progressListener;            }            /**             * 重写调用实际的响应体的contentType             * @return MediaType             */            @Override            public MediaType contentType() {                return requestBody.contentType();            }            /**             * 重写调用实际的响应体的contentLength             * @return contentLength             * @throws IOException 异常             */            @Override            public long contentLength() throws IOException {                return requestBody.contentLength();            }            /**             * 重写进行写入             * @param sink BufferedSink             * @throws IOException 异常             */            @Override            public void writeTo(BufferedSink sink) throws IOException {                if (bufferedSink == null) {                    //包装                    bufferedSink = Okio.buffer(sink(sink));                }                //写入                requestBody.writeTo(bufferedSink);                //必须调用flush,否则最后一部分数据可能不会被写入                bufferedSink.flush();            }            /**             * 写入,回调进度接口             * @param sink Sink             * @return Sink             */            private Sink sink(Sink sink) {                return new ForwardingSink(sink) {                    //当前写入字节数                    long bytesWritten = 0L;                    //总字节长度,避免多次调用contentLength()方法                    long contentLength = 0L;                    @Override                    public void write(Buffer source, long byteCount) throws IOException {                        super.write(source, byteCount);                        if (contentLength == 0) {                            //获得contentLength的值,后续不再调用                            contentLength = contentLength();                        }                        //增加当前写入的字节数                        bytesWritten += byteCount;                        //回调                        progressListener.onRequestProgress(bytesWritten, contentLength, bytesWritten == contentLength);                    }                };            }        }        interface UploadProgressListener        {            /**             * @param bytesWrite     已上传字节数             * @param contentLength 总字节数             * @param done          是否上传完成             */            void onRequestProgress(long bytesWrite, long contentLength, boolean done);        }        private void failedResponse(final Exception e, final ResultCallback callback)        {            mHandler.post(new Runnable()            {                @Override                public void run()                {                    if (callback != null)                    {                        if (e instanceof com.google.gson.JsonParseException)                        {                            callback.onError(NET_FAILED_JSON_MSG, e);                        } else if (e instanceof ConnectException)                        {                            callback.onError(NET_FAILED_LINK_UNAVIlABLE_MSG, e);                        } else if (e instanceof SocketTimeoutException)                        {                            callback.onError(NET_FAILED_TIMEOUT_MSG, e);                        } else if (e instanceof FileNotFoundException)                        {                            callback.onError(NET_FAILED_FILE_MSG, e);                        } else if (e instanceof IllegalArgumentException)                        {                            callback.onError("参数异常-"+e.getMessage(), e);                        } else                        {                            callback.onError(NET_FAILED_MSG, e);                        }                    }                }            });        }        private void onDownloadProgress(final long progress, final long allLength,                             final boolean done, final ResultCallback callback)        {            mHandler.post(new Runnable()            {                @Override                public void run()                {                    callback.onDownloadProgress(progress, allLength, done);                }            });        }        private void onUploadProgress(final long progress, final long allLength,                             final boolean done, final ResultCallback callback)        {            mHandler.post(new Runnable()            {                @Override                public void run()                {                    callback.onUploadProgress(progress, allLength, done);                }            });        }        private void successResponse(final Object object, final ResultCallback callback)        {            mHandler.post(new Runnable()            {                @Override                public void run()                {                    if (callback != null)                    {                        callback.onSuccess(object);                    }                }            });        }        /***         * 回调类,用于返回结果到前台         *         * @param <T> 传入一个泛型,会自动根据类型产生对象,在post中用处较多         */        public static abstract class ResultCallback<T extends Object>        {            Type mType;            public ResultCallback()            {                mType = getSuperclassTypeParameter(getClass());            }            public static Type getSuperclassTypeParameter(Class<?> subclass)            {                Type superclass = subclass.getGenericSuperclass();                if (superclass instanceof Class)                {                    throw new RuntimeException("ResultCallback泛型缺少对象类型");                }                ParameterizedType parameterized = (ParameterizedType) superclass;                return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);            }            public abstract void onError(String simpleMsg, Exception e);            public void onDownloadProgress(long progress, long allLength, boolean done){}            public void onUploadProgress(long progress, long allLength, boolean done){}            public abstract void onSuccess(T response);        }        /***         * 此方法用于设置https访问时证书,仅用于单向验证,inputstream为证书文件的输入流,可以将证书放到main/assets目录下,         * 也可以使用rfc命令得到字符串用 new Buffer().writeUtf(str).inputStream()得到输入流,         * 需要包含-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----         * @param certificate         */        public void setCertificate(String alias, String password, InputStream certificate)        {            try            {                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());                keyStore.load(null);                int index = 0;    //            for (InputStream certificate : certificates)    //            {    //                String certificateAlias = Integer.toString(index++);                keyStore.setCertificateEntry(alias, certificateFactory.generateCertificate(certificate));                try                {                    if (certificate != null)                        certificate.close();                } catch (IOException e)                {                }    //            }                SSLContext sslContext = SSLContext.getInstance("TLS");                KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(                        KeyManagerFactory.getDefaultAlgorithm());                keyManagerFactory.init(keyStore, password.toCharArray());                TrustManagerFactory trustManagerFactory =                        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());                trustManagerFactory.init(keyStore);                TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();                if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {                    throw new IllegalStateException("Unexpected default trust managers:"                            + Arrays.toString(trustManagers));                }else                {                    sslContext.init(null,new TrustManager[]{trustManagers[0]},new SecureRandom());                    clientDefault = clientDefault.newBuilder()                    .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0])                    .build();                }            } catch (Exception e)            {                e.printStackTrace();            }        }    }

使用:

manager = OkHttpManager.getInstance();manager.doPost(Constant.WEB_BASE + "/jpush/notifyOne", new OkHttpManager.ResultCallback<BaseResp>()                {                    @Override                    public void onError(String simpleMsg, Exception e)                    {                        Toast.makeText(PushActivity.this, simpleMsg, Toast.LENGTH_SHORT).show();                    }                    @Override                    public void onSuccess(BaseResp response)                    {                        Toast.makeText(PushActivity.this, response.getInfo(), Toast.LENGTH_SHORT).show();                    }                }, null);

其他使用方法自行研究~

0 0
原创粉丝点击