android面试收集Android_SpeakAndroid知识

Handler、AsyncTask、OkHttp、RxJava:

2017-06-20  本文已影响447人  Ricco_F
转载请注明原创出处,谢谢!

命令模式:Handler.post
享元模式:Message.obtain
模板方法模式:AsyncTask
责任链模式:OkHttp
建造者模式:Response、Request
原型模式:OkHttpClient
观察者模式:RxJava

分析源码,我还没那个实力,就不写了,但原理还是要知道的。如果被面试官问了,说两个就可以了,别太认真,小心hold不住!

Android中的线程通信机制:消息机制

Android 中消息模型伪代码实现?

class Message{
    Object obj;用于存储对象类型数据
    int what;表示你要做什么
    ...
}
class MessageQueue{
    Object[] messages;
    void put(Message msg){}
    Message take(){}
}
class Looper{
    MessageQueue msgQ;
    void loop(){
        while(isLoop){}
    }
    void cancel(){}
    ...
}
class Handler{
    void sendMessage(Message msg){}
    void handleMessage(Message msg){}
    ...
}

在Android系统中,主线程不可以执行耗时操作,子线程可以执行耗时却不可以直接更新UI,所以,当子线程在执行耗时操作的过程中,如果需要更新UI,则可以发出一个“消息”给主线程,当主线程收到该“消息”后,对“消息”进行处理,即更新UI,从而完成主线程和子线程的协作。
在消息机制中,会使用到:

Handler

通过调用Handler对象的sendMessage(Message)方法可以在子线程中向主线程发送消息。
通过重写void handleMessage(Message)方法可以决定如何处理消息,Handler默认是运行在主线程的,所以,可以直接更新UI。

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

Handler类有send???()系列方法、sendEmpty???()系列方法、post???()系列方法,都可以实现发送消息,具体的使用应该根据实际情况来进行选取,在不熟练的情况下,始终使用sendMessage(Message)即可。
有3种处理消息的方式,其中,在获取Message对象时,指定Message中的Runnable callback这种方式使用相对比较麻烦,一般不推荐,至于是继承自Handler,还是实现Handler.Callback可以自由选择。

Handler在哪个线程处理消息?

在默认情况下,Handler是在主线程处理消息的,所以,可以直接更新UI。
不可以直接在子线程中创建Handler对象,必须先调用过Looper.prepare()方法,且,Looper必须调用了loop()方法才会轮循消息队列,取出消息交给Handler处理。
在默认情况下,主线程已经存在调用了prepare()和loop()方法的Looper,所以,在主线程中创建Handler对象时不需要考虑Looper的问题。
Handler在哪个线程处理消息,完全取决于该Handler对象关联到的是哪个线程的Looper对象!即:如果在子线程创建Handler,关联到的是主线程的Looper对象,该Handler会在主线程处理线程。
在没有显式的指定Looper对象时,会默认获取创建Handler对象的线程的Looper,可表现为:在哪个线程创建Handler,就在哪个线程处理消息。
如果已经显式的指定Looper对象,则由Looper对象的线程来决定在哪个线程处理消息。

Message

HandlerThread与IntentService

HandlerThread是一个线程类,它的作用是便捷的获取一个运行在子线程的Looper对象。
在使用HandlerThread时,必须遵循以下流程,不可调整代码的先后顺序:

使用HandlerThread的目的只是为了获取运行在子线程的Looper,进而,可以通过该Looper创建出在子线程处理消息的Handler,这样的Handler在接收到消息后可以直接执行耗时操作,当然,这样的Handler是不可以直接更新UI的。
普通的Service由于进程优先级较高,所以适合执行耗时操作,但是,Service也是运行在主线程的,所以在执行耗时操作时,也是必须开启子线程的,同时,每个Service在使用完成后应该停止。总结的结果就是:使用Service多半需要另启子线程,且使用完成后停止该Service。

使用线程的方式

AsyncTask

在使用AsyncTask时,需要自定义类继承自AsyncTask,首要任务是确定3个泛型:

执行AsyncTask时,调用AsyncTask对象的execute(Params... params)方法即可
使用AsyncTask时,必须自定义子类实现继承,并且优先确定3个泛型,在这3个泛型中,不需要使用的类型可以使用Void表示,其中,doInBackground()方法是默认运行在子线程的,可以执行耗时操作,publishProgress()方法是用于在doInBackground()的执行过程中提交进度的,如果需要处理进度的显示,必须重写onProgressUpdate()方法,每次执行publishProgress()都会导致onProgressUpdate()被回调,onProgressUpdate()是运行在主线程的,可以直接更新UI,当doInBackground()执行完毕,onPostExecute()将被回调1次,该方法也是运行在主线程的,可以直接更新UI。
当需要执行任务时,先创建任务对象,然后调用execute()方法执行任务。
当需要终止任务时,可以调用任务对象的cancel(true)方法以实现终止。
假设有任务A、任务B均是继承AsyncTask实现的,那么,不管创建多少个任务A、任务B的对象,这所有的任务都将是依次执行的。

终止AsyncTask

调用任务对象的cancel(true)方法可以终止任务,实际表现为onProgressUpdate()方法和onPostExecute()方法将不再被回调,而doInBackground()并不会停止后台的运行!
不推荐使用这样的方式终止任务,在条件允许的情况下,应该使得任务自然运行结束以实现终止的效果

重点来了OkHttp、RxJava

在写OkHttp、RxJava前,我想问大家,你有多长时间没写过Handler,AsyncTask了?我在Android技术群进行询问的时候,没想到引发了一场口水仗,但有一位的观点,我很认同。

当然,也有很多反对的意见。
所以,现在每当看到有关Handler,AsyncTask的技术帖,我都很反感,可这又是面试高频率题,没办法,Handler还是要了解。

OkHttp使用

compile 'com.squareup.okhttp3:okhttp:3.8.1'

public class HttpUtils {
    public static void sendOkHttpRequest(String address, Callback callback) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(address).build();
        client.newCall(request).enqueue(callback);
    }
}
HttpUtils.sendOkHttpRequest(address, new Callback() {
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        final String responseText = response.body().string();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
            }
        });
    }
    @Override
    public void onFailure(Call call, IOException e) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
            }
        });
    }
});

POST请求

try {
            OkHttpClient okHttpClient = new OkHttpClient();
            RequestBody requestBody = new FormBody.Builder().add("username", "admin").add("password", "123456").build();
            Request request = new Request.Builder().url("http://www.baidu.com").post(requestBody).build();
            Response response = okHttpClient.newCall(request).execute();
            String responseText = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }

RxJava使用

老罗RxJava视频百度云
链接:http://pan.baidu.com/s/1pLPp4RD 密码:zx9h

public class RxUtils {

    private static final String TAG = RxUtils.class.getSimpleName();

    /**
     * 使用create方式
     */
    public static void createObserable() {
        //定义被观察者,
        Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                if (!subscriber.isUnsubscribed()) {
                    subscriber.onNext("hello");
                    subscriber.onNext("world");
                    subscriber.onCompleted();
                }
            }
        });
        Subscriber<String> showsub = new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.i(TAG, "onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                Log.i(TAG, e.getMessage());
            }

            @Override
            public void onNext(String s) {
                Log.i(TAG, "result-->>" + s);
            }
        };
        observable.subscribe(showsub);//关联被观察者
    }
}

RxJava+OkHttp实现登录

public class LoginUtils {

    private OkHttpClient client;

    public LoginUtils() {
        client = new OkHttpClient();
    }

    /**
     * 定义了login操作,使用RxAndroid的编程思想
     * @param url
     * @param params
     * @return Json字符串
     */
    public Observable<String> login(String url,Map<String,String> params){
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
               if (!subscriber.isUnsubscribed()){
                   FormBody.Builder builder = new FormBody.Builder();
                   if (params!=null&&!params.isEmpty()){
                       for(Map.Entry<String,String> entry:params.entrySet()){
                           builder.add(entry.getKey(),entry.getValue());
                       }
                   }
                   RequestBody requestBody = builder.build();
                   //构建post请求
                   Request request = new Request.Builder().url(url).post(requestBody).build();
                   client.newCall(request).enqueue(new Callback() {
                       @Override
                       public void onFailure(Call call, IOException e) {
                           subscriber.onError(e);
                       }

                       @Override
                       public void onResponse(Call call, Response response) throws IOException {
                          if (response.isSuccessful()){
                              subscriber.onNext(response.body().string());
                          }
                           subscriber.onCompleted();//访问结束
                       }
                   });
               }
            }
        });
    }
}
button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Map<String, String> params = new HashMap<String, String>();
                params.put("username", "admin";
                params.put("password", "123456");

                new LoginUtils().login(URL_LOGIN, params).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        dialog.dismiss();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i(TAG, e.getMessage());
                    }

                    @Override
                    public void onNext(String s) {
                        dialog.show();
                        Log.i(TAG,s);
                       }
                    }
                });
            }
        });
上一篇下一篇

猜你喜欢

热点阅读