Android 异步任务和监视器

Android 异步任务和监视器,android,android-asynctask,monitor,Android,Android Asynctask,Monitor,我的问题是: 我需要在服务器上执行几个请求。这些请求必须一个接一个地提出,以避免混淆。为此,我使用监视器 以下是我到目前为止得出的结论: public class TestActivity extends Activity { private String key; private HashMap<String, String> values; @Override public void onCreate(Bundle savedInstanceState) {

我的问题是:

我需要在服务器上执行几个请求。这些请求必须一个接一个地提出,以避免混淆。为此,我使用监视器

以下是我到目前为止得出的结论:

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);
    }
  }
}
我需要将值保存在
列表中
并知道哪个值对应于什么内容(因此是监视器)

我的问题是,我一直在日志中收到错误消息:

Can't create handler inside thread that has not called Looper.prepare()
我搜索了网络,找到了一些有这个问题的人,查看了答案,大多数人说我需要使用处理器。处理程序也不起作用。我试着把线换成线

handler = new Handler(Looper.getMainLooper);
handler.post(new Runnable //...
//...
但它只是冻结


我准备承认我的方法是错误的,如果你认为我走到了死胡同,我会从头开始。您会怎么做?

您可能已经找到了解决方案,但在任何情况下,您都可以使用
执行器执行请求的顺序:

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);
                }
            });
        }
    }
}
公共类SequentialTaskExampleActivity扩展活动{
/**
*一次只执行一个作业,按照给定的顺序执行。
*/
private Executor Executor=Executors.newSingleThreadExecutor();
私有映射值=新的HashMap();
私有文本视图文本视图;
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
textView=新的textView(此);
textView.setTextSize(24);
setContentView(文本视图);
//初始化作业并添加到队列
ArrayList=新建ArrayList();
列表。添加(“foo”);
列表。添加(“酒吧”);
列表。添加(“baz”);
for(字符串键:列表){
执行者。执行(新作业(密钥));
}
}
public void addToResult(字符串键、字符串值){
value.put(键、值);
//将结果显示到用户界面
textView.setText(String.format(“%s%s=>%s\n”,textView.getText(),key,value));
}
私有类作业实现可运行{
私钥;
公共作业(字符串键){
this.key=key;
}
@凌驾
公开募捐{
//模拟工作
试一试{
线程。睡眠(10*1000);
}捕捉(中断异常e){
e、 printStackTrace();
}
//检索结果
最终字符串值=键+“来自服务器”;
//将结果发布回用户界面
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
addToResult(键、值);
}
});
}
}
}

如果您以API11+为目标,那么可以指定一个特定的执行器来代替AsyncTask(事实上,我认为默认的新行为是串行处理)。在任何情况下,您都应该在UI线程上创建和执行AsyncTask;这是确保AsyncTask.onPostExecute()正确运行的唯一方法。

您可能已经找到了解决方案,但在任何情况下,这里有一种方法可以使用
执行器强制执行请求的顺序:

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);
                }
            });
        }
    }
}
公共类SequentialTaskExampleActivity扩展活动{
/**
*一次只执行一个作业,按照给定的顺序执行。
*/
private Executor Executor=Executors.newSingleThreadExecutor();
私有映射值=新的HashMap();
私有文本视图文本视图;
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
textView=新的textView(此);
textView.setTextSize(24);
setContentView(文本视图);
//初始化作业并添加到队列
ArrayList=新建ArrayList();
列表。添加(“foo”);
列表。添加(“酒吧”);
列表。添加(“baz”);
for(字符串键:列表){
执行者。执行(新作业(密钥));
}
}
public void addToResult(字符串键、字符串值){
value.put(键、值);
//将结果显示到用户界面
textView.setText(String.format(“%s%s=>%s\n”,textView.getText(),key,value));
}
私有类作业实现可运行{
私钥;
公共作业(字符串键){
this.key=key;
}
@凌驾
公开募捐{
//模拟工作
试一试{
线程。睡眠(10*1000);
}捕捉(中断异常e){
e、 printStackTrace();
}
//检索结果
最终字符串值=键+“来自服务器”;
//将结果发布回用户界面
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
addToResult(键、值);
}
});
}
}
}

如果您以API11+为目标,那么可以指定一个特定的执行器来代替AsyncTask(事实上,我认为默认的新行为是串行处理)。在任何情况下,您都应该在UI线程上创建和执行AsyncTask;这是确保
AsyncTask.onPostExecute()
正常运行的唯一方法。

对于错误消息的简短回答,必须在UI线程上调用AsyncTask.execute(),请检查API。你的应用程序运行的目标是什么Android版本?我使用的是API 8(Android 2.2)。至于UI线程,我尝试使用
runOnUiThread()
,但我的应用程序冻结了。对于错误消息的简短回答,必须在UI线程上调用AsyncTask.execute(),请检查API。你的应用程序运行的目标是什么Android版本?我使用的是API 8(Android 2.2)。至于UI线程,我尝试使用
runOnUiThread()
,但我的应用程序冻结了。