1

简短的故事:
我需要将一些代码从我的 UI 线程中移出到后台线程中,并且我需要能够将五个变量值传递到该后台线程并从中接收五个值。我希望有人可以提供一个简单的工作示例,假设下面的代码是我的代码,而注释行之间的位是需要移动的。

更长的故事:
我的 UI 线程中的部分代码需要大约 15 秒才能完成。在此期间屏幕冻结。我不介意屏幕冻结,因为用户此时不需要与屏幕交互。问题是我也有一个OnKeyListener在我的 UI 线程中,它不赞成延迟。如果用户在 15 秒延迟期间按下任何键盘键,将导致大约 5 秒后出现 ANR(应用程序无响应)提示。我需要将耗时的代码移到可以在后台运行的单独线程中。我花了大约 13 个小时试图弄清楚如何使用 AsyncTask 和其他方法来做到这一点,但无法弄清楚如何将五个变量值传递到线程中并从中接收五个值。我希望有人可以提供一个简单的工作示例,假设下面的代码是我的代码,而注释行之间的位是需要移动的。

       myButton.setOnClickListener(new OnClickListener()
       {
          public void onClick(View arg0)
          {
          Integer userNum1 = 12; //pretend these numbers are user inputted (ever-changing)
          Integer userNum2 = 8;
          Integer userNum3 = 2;
          Integer userNum4 = 31;
          Integer userNum5 = 17;
          Integer userMultiplier = 9;
          //-----------------------------
             for (int i = 0; i < 15; i++)
             {
             userNum1 = userNum1 * userMultiplier;
             userNum2 = userNum2 * userMultiplier;
             userNum3 = userNum3 * userMultiplier;
             userNum4 = userNum4 * userMultiplier;
             userNum5 = userNum5 * userMultiplier;

             try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}   
             }
          //-----------------------------
          String myString1 = String.valueOf(userNum1);
          String myString2 = String.valueOf(userNum2);
          String myString3 = String.valueOf(userNum3);
          String myString4 = String.valueOf(userNum4);
          String myString5 = String.valueOf(userNum5);
          }
       });  



编辑:
这是我最终为解决这个问题所做的事情:

public Integer myTaskDone = 0;  
public Integer userNum1 = 0;    
public Integer userNum2 = 0;    
public Integer userNum3 = 0;    
public Integer userNum4 = 0;    
public Integer userNum5 = 0;
public Integer userMultiplier = 0;
public String[] valueTransporter = new String[20];





myButton.setOnClickListener(new OnClickListener()
{
   public void onClick(View arg0)
   {
   userNum1 = 12;
   userNum2 = 8;
   userNum3 = 2;
   userNum4 = 31;
   userNum5 = 17;
   userMultiplier = 9;

   valueTransporter[0] = String.valueOf(userNum1);
   valueTransporter[1] = String.valueOf(userNum2);
   valueTransporter[2] = String.valueOf(userNum3);
   valueTransporter[3] = String.valueOf(userNum4);
   valueTransporter[4] = String.valueOf(userNum5);
   valueTransporter[5] = String.valueOf(userMultiplier);

   new myTask().execute(valueTransporter);
   }
});  





//Had to move the last section of code into this new thread, otherwise the code would have executed before myTask finished.
//All this thread does is frequently check myTaskDone to see if it equals 1 (if it does equal 1, the last section of code will be executed).
final Handler mHandler = new Handler();
new Thread(new Runnable()
{
@Override
   public void run()
   {
      while (true)
      {
         try
         {
         Thread.sleep(10); 
            mHandler.post(new Runnable()
            {
            @Override
               public void run() 
               {
                  if (myTaskDone == 1)
                  {
                  myTaskDone = 0;
                  String myString1 = String.valueOf(userNum1);
                  String myString2 = String.valueOf(userNum2);
                  String myString3 = String.valueOf(userNum3);
                  String myString4 = String.valueOf(userNum4);
                  String myString5 = String.valueOf(userNum5);
                  }
               }
            });
         } catch (Exception e) {}
      }
   }  
}).start();




public class myTask extends AsyncTask<String,String,String[]> 
{
    @Override

    protected String[] doInBackground(String... valueTransporter)
    {

    //Our values have been transported in via valueTransporter. Put those values back into variables so we can work on them.    
    Integer userNum1 = Integer.parseInt(valueTransporter[0]);   
    Integer userNum2 = Integer.parseInt(valueTransporter[1]);
    Integer userNum3 = Integer.parseInt(valueTransporter[2]);
    Integer userNum4 = Integer.parseInt(valueTransporter[3]);
    Integer userNum5 = Integer.parseInt(valueTransporter[4]);
    Integer userMultiplier = Integer.parseInt(valueTransporter[5]);

       //Do work
       //-----------------------------
       for (int i = 0; i < 15; i++)
       {
       userNum1 = userNum1 * userMultiplier;
       userNum2 = userNum2 * userMultiplier;
       userNum3 = userNum3 * userMultiplier;
       userNum4 = userNum4 * userMultiplier;
       userNum5 = userNum5 * userMultiplier;

       try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}   
       }
       //-----------------------------

    //Now that the work has been done on the values, load them back into valueTransporter.
    valueTransporter[0] = String.valueOf(userNum1);
    valueTransporter[1] = String.valueOf(userNum2);
    valueTransporter[2] = String.valueOf(userNum3);
    valueTransporter[3] = String.valueOf(userNum4);
    valueTransporter[4] = String.valueOf(userNum5);

    return valueTransporter;
    }

    protected void onPostExecute(String[] valueTransporter) 
    {
    //Get the values out of valueTransporter and into the original variables used by the UI thread.
    userNum1 = Integer.parseInt(valueTransporter[0]);   
    userNum2 = Integer.parseInt(valueTransporter[1]);
    userNum3 = Integer.parseInt(valueTransporter[2]);
    userNum4 = Integer.parseInt(valueTransporter[3]);
    userNum5 = Integer.parseInt(valueTransporter[4]);

    myTaskDone = 1;
    }

}  
4

1 回答 1

0

您可以通过将输出放在 MyTask 上来清理它:

  • 为 MyTask 上的每个输出值创建一个字段
  • 在 onPostExecute() 中设置它们的值
  • 将 'boolean myTaskDone' 更改为 'MyTask finishedTask'
  • 将“myTaskDone = 1”更改为“finishedTask = this”
  • 将 'if (myTaskDone == 1)' 更改为 'if (finishedTask != null)'

然后,您可以从任务对象中提取值,然后可以删除 valueTransporter。

此外,通常不是循环,您可以从 onPostExecute() 调用一个方法,并将所有输出值(或 MyTask)作为参数,并且该方法可以执行接下来的任何操作。

于 2013-06-13T02:23:59.560 回答