Foreword
Some students always ask me about school recruit this year's retreat became a gold and three silver four gold, four silver five, and what knowledge I changed ready to go review the interview, however, to be prepared very large knowledge, knowledge of which talk about today one. An article on HandlerThread
parsing
Document notes ~
Summary knowledge of PDF content GitHub subsequent updates, like the impact of gold and three silver four small partners can look and see, welcome Star
( pulled left GitHub link, you need access to relevant content such as interviews can find their own )
HTTPS: // github.com/xiangjiana/Android-MS
more complete project download. To be continued. Source. Graphic knowledge subsequent upload github.
You can click on my link I get
scenes to be used
HandlerThread
Google is helping us a good package, can be used to perform a number of time-consuming operations, without the need to open multiple threads, which is adopted Handler
and Looper
implemented.
Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called
How to use HandlerThread
?
1. Create an HandlerThread
instance of an object
HandlerThread handlerThread = new HandlerThread("myHandlerThread" );
This parameter indicates the thread's name, I could choose.
1. Start we created HandlerThread
a thread
handlerThread.start();
Our handlerThread
and Handler bound. Remember how to bind together Handler and thread objects do? Actually very simple, it is to thread looper
and Handler
bound, as follows:
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
checkForUpdate();
if(isUpdate){
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
}
};
Note that you must follow the above three steps, in the following explanation of the source when it will analyze the reasons
Complete test code as follows
public class MainActivity extends AppCompatActivity {
private static final int MSG_UPDATE_INFO = 0x100;
Handler mMainHandler = new Handler();
private TextView mTv;
private Handler mThreadHandler;
private HandlerThread mHandlerThread;
private boolean isUpdate = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = (TextView) findViewById(R.id.tv);
initHandlerThread();
}
private void initHandlerThread() {
mHandlerThread = new HandlerThread("xujun");
mHandlerThread.start();
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
checkForUpdate();
if (isUpdate) {
mThreadHandler.sendEmptyMessage(MSG_UPDATE_I NFO);
}
}
};
}
/**
* 模拟从服务器解析数据
*/
private void checkForUpdate() {
try {
//模拟耗时
Thread.sleep(1200);
mMainHandler.post(new Runnable() {
@Override
public void run() {
String result = "实时更新中,当前股票行情:<font color='red'>%d</font>";
result = String.format(result, (int) (Math.r andom() * 5000 + 1000));
mTv.setText(Html.fromHtml(result));
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
protected void onResume() {
isUpdate = true;
super.onResume();
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
@Override
protected void onPause() {
super.onPause();
isUpdate = false;
mThreadHandler.removeMessages(MSG_UPDATE_INFO);
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandlerThread.quit();
mMainHandler.removeCallbacksAndMessages(null);
}
}
Run the above test code, the following effects can be seen in FIG. (Example not appropriate, the scene is used mainly in handleMessage
the time-consuming operation)
HandlerThread
Source code analysis
Official source code is as follows, based on sdk23, you can see, only a hundred lines of code.
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
/**
* Call back method that can be explicitly overridden if nee ded to execute some
* setup before Looper loops.
*/
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
//持有锁机制来获得当前线程的Looper对象
synchronized (this) {
mLooper = Looper.myLooper();
//发出通知,当前线程已经创建mLooper对象成功,这里主要是通知g etLooper方法中的wait notifyAll();
}
//设置线程的优先级别
Process.setThreadPriority(mPriority);
//这里默认是空方法的实现,我们可以重写这个方法来做一些线程开始之前 的准备,方便扩展
onLooperPrepared();
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// 直到线程创建完Looper之后才能获得Looper对象,Looper未创建成功 ,阻塞 synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
/**
* Returns the identifier of this thread. See Process.myTid( ).
*/
public int getThreadId() {
return mTid;
}
}
1) First, let's look at its construction method
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
There are two constructors, one parameter and two parameters, name represents the name of the current thread, priority
thread priority level
2) Then we look at the run()
way in which we can see that we run method initializes a Looper
, and set the thread's priority
public void run() {
mTid = Process.myTid();
Looper.prepare();
//持有锁机制来获得当前线程的Looper对象
synchronized (this) {
mLooper = Looper.myLooper();
//发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLo oper方法中的wait notifyAll();
}
//设置线程的优先级别
Process.setThreadPriority(mPriority);
//这里默认是空方法的实现,我们可以重写这个方法来做一些线程开始之前的准备 ,方便扩展
onLooperPrepared();
Looper.loop();
mTid = -1;
}
- Remember earlier we said that we use
HandlerThread
when we must call the start () method, then we can put ourHandlerThread
and our handler tied to it? Actually, the reason is that we are in therun()
method began our initializationlooper
, which we callHandlerThread
thestart()
when the method, the thread to the virtual machine scheduling, call the run method automatically by a virtual machine
mHandlerThread.start();
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
checkForUpdate();
if(isUpdate){
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
}
};
- Here, we use lock mechanism and why
notifyAll()
; because we can fromgetLooper()
know methods
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// 直到线程创建完Looper之后才能获得Looper对象,Looper未创建成功,阻塞
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
Summary: in obtaining mLooper
a problem when a synchronization object only when the thread is created successfully and Looper
after the object is created successfully also to get mLooper
value. Wait wait method and the run method of this notifyAll
method together to complete synchronization problems.
3) Then we look at the quit
methods and quitSafe
methods
//调用这个方法退出Looper消息循环,及退出线程
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
//调用这个方法安全地退出线程
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
Tracking these two methods is easy to know only two methods will eventually call MessageQueue
the quit(boolean safe)
method
void quit(boolean safe) {
if (!mQuitAllowed) { throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
//安全退出调用这个方法
if (safe) {
removeAllFutureMessagesLocked();
} else {//不安全退出调用这个方法
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previou sly false.nativeWake(mPtr);
}
}
Unsafe calls removeAllMessagesLocked()
; this method, we look at how to deal with this method is, in fact, is to go through Message
the list, remove all the callback information, and reset to null.
private void removeAllMessagesLocked() {
Message p = mMessages;
while (p != null) {
Message n = p.next;
p.recycleUnchecked();
p = n;
}
mMessages = null;
}
Safely calls removeAllFutureMessagesLocked()
; this method, it will be based on Message.when
this property to determine whether our current message queue is processing the message, no message is being processed, then simply remove all callbacks being processed, then wait for the message processing is complete and then exit the loop . So, to say quitSafe()
it is safe, but quit()
the method is not safe, because the quit method regardless of whether the message is being processed, directly remove all callbacks.
private void removeAllFutureMessagesLocked() {
final long now = SystemClock.uptimeMillis();
Message p = mMessages;
if (p != null) {
//判断当前队列中的消息是否正在处理这个消息,没有的话,直接移除所有 回调
if (p.when > now) {
removeAllMessagesLocked();
} else {//正在处理的话,等待该消息处理处理完毕再退出该循环
Message n;
for (;;) {
n = p.next;
if (n == null) {
return;
}
if (n.when > now) {
break;
}
p = n;
}
p.next = null;
do {
p = n;
n = p.next;
p.recycleUnchecked();
} while (n != null);
}
}
}
Document notes ~
Summary knowledge of PDF content GitHub subsequent updates, like the impact of gold and three silver four small partners can look and see, welcome Star
( pulled left GitHub link, you need access to relevant content such as interviews can find their own )
HTTPS: // github.com/xiangjiana/Android-MS
more complete project download. To be continued. Source. Graphic knowledge subsequent upload github.
You can click on my link I get