我正在尝试从名为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();
}
}
}
答案 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.
}