当Thread.sleep()在另一个线程中调用时,UI-Thread被阻止

时间:2017-05-29 08:02:47

标签: java android multithreading

我正在尝试从名为Runnable的{​​{1}}中读取SD卡中的文本文件,并在UI-Thread中相应地更新PcmDataReader
我使用TextView statusTextView将消息从handler传递给UI-Thread。

为了能够观察到PcmDataReader statusTextView的变化Thread.sleep(5000) PcmDataReader。{
问题是UI-Thread被阻塞,直到文件i / o&睡眠已经结束了最后更新,即“文件阅读完成。。”仅显示在statusTextview上。
我在这里失踪了什么?
以下是我的代码:



MainActivity.java:

package com.example.pcmreader;

import android.Manifest;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Button;


public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private TextView statusTextView ;
    priavte Button updateButton;

    private PcmDataReader pcmData = new PcmDataReader();
    private static Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        handler = new Handler()
        {
            @Override
            public void handleMessage (Message message)
            {
                String msg = (String) message.obj;
                if (statusTextView != null)
                    statusTextView.setText(msg);
            }

        };

        setContentView(R.layout.main);

        statusTextView= (TextView) findViewById(R.id.statusTextView);

        ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, 100);

    updateButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View view)
    {
    statusTextView.setText("Initiating Read .. ");
        pcmData.run();

    }

    public static Handler getHandler ()
    {
        return handler;
    }
}



PcmDataReader.java:

package com.example.pcmreader;


import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;


public class PcmDataReader implements Runnable
{
    private int [] samples = new int[6000]; 
    private int i;
    private boolean completedReading;
    private File sdcard = Environment.getExternalStorageDirectory();
    private File file = new File(sdcard,"rishav_log.txt");

    @Override
    public void run() 
    {

        i=0;
        completedReading = false;
        try
        {
            BufferedReader br = new BufferedReader(new FileReader(file));
            String line;
            Handler uiHandler= MainActivity.getHandler();
            Message msg = uiHandler.obtainMessage();
            msg.obj="File openned, Reading data..";
            uiHandler.sendMessage(msg);

            while ((line = br.readLine()) != null)
                 samples[i++]=Integer.parseInt(line);

            Thread.sleep(5000); //dummy sleep to observe the update of textView in UI thead
            br.close();
            completedReading = true;

            msg = uiHandler.obtainMessage();
            msg.obj="File Reading Complete..";
            uiHandler.sendMessage(msg);
        }
        catch (IOException e)
        {
            Log.i("file read",e.getMessage());
        } 
    catch (InterruptedException e)
    {
            e.printStackTrace();
        }
    }

}

2 个答案:

答案 0 :(得分:3)

调用runnable应该在单独的线程中。

替换

pcmData.run();

Thread t1 =new Thread(pcmData);  
t1.start(); 

答案 1 :(得分:1)

UI线程冻结,因为您在同一个线程中调用Thread.sleep()

@Override
public void onClick(View view) {
    statusTextView.setText("Initiating Read .. ");
    pcmData.run(); // PcmDataReader.run() will happen in the UI thread

}

修复相对容易:

@Override
public void onClick(View view) {
    statusTextView.setText("Initiating Read .. ");
    ExecutorService executor = Executors.newSingleThreadExecutor(); // this can come from somplace else.
    // Actually, it better comes from someplac else.
    executor.submit(pcmData); // this is how to run in in a background thread.
    // executor.shutdown(); // this is necessary only if you create the executor in the same method.
    // Otherwise, creating and killing background threads is a matter of your apps strategy.
}