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



我正在尝试在Runnable中读取一个名为PcmDataReader的SD-CARD的文本文件,并在UI-Thread中更新TextView statusTextView
我正在使用handler将消息从PcmDataReader传递到UI-Thread。

为了能够观察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();
        }
    }
}

呼叫运行应在>单独的线程中。

替换

pcmData.run();

to

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

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.
}

最新更新