这是我的问题:
我需要在服务器上执行几个请求。为了避免混淆,这些请求必须一个接一个地提出。为此,我正在使用监视器。
到目前为止,这是我提出的内容:
public class TestActivity extends Activity
{
private String key;
private HashMap<String, String> values;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
values = new HashMap<String, String>();
ArrayList<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
list.add("baz");
createValues(list);
}
private void createValues(final ArrayList<String> list)
{
Thread thread = new Thread(new Runnable() {
@Override
public void run()
{
key = null;
for (String element : list)
{
if (key != null) // Every time except the first time.
{
synchronized (key)
{
try
{
key.wait();
}
catch (InterruptedException e)
{
}
}
}
key = element;
DataProcessor dataProcessor = new DataProcessor();
dataProcessor.execute("Processed " + element);
}
}
});
}
private void putDataInValue(String element)
{
synchronized (key)
{
values.put(key, element);
key.notify();
}
}
private class DataProcessor extends AsyncTask<String, Void, String>
{
@Override
protected String doInBackground(String... params)
{
// Fetching data on a server. This takes time.
try
{
Thread.sleep(10000);
}
catch (InterruptedException e)
{
}
return params[0] + " from the server";
}
@Override
protected void onPostExecute(String result)
{
putDataInValue(result);
}
}
}
之后,我想要的是
values
的内容是:[
"foo" => "Processed foo from the server",
"bar" => "Processed bar from the server",
"baz" => "Processed baz from the server"
]
我需要将值保留在
list
中,并知道哪个对应于什么内容(因此是监视器)。我的问题是我在LogCat中不断收到错误消息:
Can't create handler inside thread that has not called Looper.prepare()
我在网上搜索,发现了一些有此问题的人,查看了答案,其中大多数人说我需要使用处理程序。处理程序也不起作用。我尝试通过替换线程
handler = new Handler(Looper.getMainLooper);
handler.post(new Runnable //...
//...
但它只是冻结。
我准备承认我的方法是错误的,如果您认为我处于死胡同,请从头开始。你会怎么做 ?
最佳答案
您可能已经找到了解决方案,但是无论如何,这是一种可以使用Executor
强制执行请求顺序的方法:
public class SequentialTaskExampleActivity extends Activity {
/**
* will only execute one job at a time, in the order given to it.
*/
private Executor executor = Executors.newSingleThreadExecutor();
private Map<String, String> values = new HashMap<String, String>();
private TextView textView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = new TextView(this);
textView.setTextSize(24);
setContentView(textView);
// Initialise jobs and add to queue
ArrayList<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
list.add("baz");
for (String key : list) {
executor.execute(new Job(key));
}
}
public void addToResult(String key, String value) {
values.put(key, value);
// display result to UI
textView.setText(String.format("%s %s => %s\n", textView.getText(), key, value));
}
private class Job implements Runnable {
private String key;
public Job(String key) {
this.key = key;
}
@Override
public void run() {
// simulate work
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// retrieve result
final String value = key + " from the server";
// post result back to UI
runOnUiThread(new Runnable() {
@Override
public void run() {
addToResult(key, value);
}
});
}
}
}
如果您的目标是API 11+,则可以指定要与AsyncTask一起使用的特定执行程序(实际上,我认为默认的新行为是串行处理)。无论如何,您应该始终在UI线程上创建并执行AsyncTask;这是确保
AsyncTask.onPostExecute()
正常运行的唯一方法。关于android - AsyncTask和监视器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8374849/