Недавно я создал пользовательский view
с нитью сына. Чтобы манипулировать компонентами в MainActivity
, я написал метод обратного вызова и использовал handler
для обработки message
, но когда я прервал поток сына, процесс handleMessage запустился после основного потока.
Я пытался использовать Thread.sleep
, но мне не удалось. Понравилось:
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Первоначальный проект был слишком велик, поэтому я переписал похожую демонстрацию.
MainActivity
:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Handler handler;
Message message;
private Button bt_start,bt_finish;
Thread thread1;
private MyView myView;
private TextView tv;
//锁对象
private final Object lock = new Object();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initAction();
}
public void initView() {
bt_start = (Button)findViewById(R.id.bt_start);
bt_finish = (Button)findViewById(R.id.bt_finish);
myView = (MyView)findViewById(R.id.myView);
tv = (TextView)findViewById(R.id.textView);
bt_start.setOnClickListener(this);
bt_finish.setOnClickListener(this);
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
String s = (String)msg.obj;
tv.setText(s);
System.out.println("handling Meassage1 ");
break;
case 2:
System.out.println("handling Meassage2 ");
break;
}
}
};
}
public void initAction() {
myView.setCallbackListener(new MyView.CallbackListener() {
@Override
public void updateData(String testData) {
message = new Message();
message.what = 1;
message.obj = testData;
handler.sendMessage(message);
}
@Override
public void clear() {
tv.setText("");
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_finish:
if (thread1 != null)
thread1.interrupt();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finish");
myView.reset();
break;
case R.id.bt_start:
thread1 = new Thread(myView.new InnerThread(lock));
thread1.start();
break;
}
}
}
Код MyView
здесь:
public class MyView extends View {
public Paint mPaint;
private String testData;
private CallbackListener callbackListener;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
testData = "test";
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.YELLOW);
canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
}
//InnerThread
public class InnerThread implements Runnable {
private Object lock;
@Override
public void run() {
mainFun();
}
public void test1(){
System.out.println("before test1 wait");
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException ie){
System.out.println("test1 is interrupted");
Thread.currentThread().interrupt();
}
System.out.println("after test1 wait");
}
public void test2(){
System.out.println("before test2 wait");
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException ie){
System.out.println("test2 is interrupted");
Thread.currentThread().interrupt();
}
System.out.println("after test2 wait");
}
public void mainFun() {
test1();
callbackListener.updateData(testData);
test2();
}
public InnerThread(Object lock) {
super();
this.lock = lock;
}
}
public interface CallbackListener {
void updateData(String testData);
void clear();
}
public void setCallbackListener(CallbackListener ls) {
this.callbackListener = ls;
}
public void reset() {
callbackListener.clear();
}
}
Наконец, activity_main.xml
здесь:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.bug.MyView
android:id="@+id/myView"
android:layout_width="match_parent"
android:layout_height="300px" />
<Button
android:id="@+id/bt_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start" />
<Button
android:id="@+id/bt_finish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="finish" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
Я ожидаю результат handleMessage(Message msg)
до результата System.out.println("finish");
, но фактический результат здесь:
2019-05-17 17:11:06.301 31565-31591/com.example.bug I/System.out: before test1 wait
2019-05-17 17:11:08.671 31565-31591/com.example.bug I/System.out: test1 is interrupted
2019-05-17 17:11:08.671 31565-31591/com.example.bug I/System.out: after test1 wait
2019-05-17 17:11:08.671 31565-31591/com.example.bug I/System.out: before test2 wait
2019-05-17 17:11:08.671 31565-31591/com.example.bug I/System.out: test2 is interrupted
2019-05-17 17:11:08.671 31565-31591/com.example.bug I/System.out: after test2 wait
2019-05-17 17:11:09.173 31565-31565/com.example.bug I/System.out: finish
2019-05-17 17:11:09.178 31565-31565/com.example.bug I/System.out: handling Meassage1
Я не могу найти ошибку, поэтому я предполагаю, что я что-то делаю неправильно. В чем проблема?