如何*不*使用runOnUiThread

时间:2012-08-11 05:24:56

标签: java android multithreading

正如您在标题中看到的那样,我每次需要时都尝试不使用runOnUiThread。我将在后面解释我的意思,但首先,这是我当前的代码(部分):

private void filePaste()
{
  final File src = new File(FileClip); //Source file (as a string)
  final File dest = new File(myPath.getText()+"/"+src.getName()); //Destination file
  final ProgressDialog dlg = new ProgressDialog(AppContext);

  final Thread copythread = new Thread(new Runnable() {
    public void run() {
      if(FileClip==null)
        Main.this.runOnUiThread(new Runnable() {
          public void run(){
            toast(getString(R.string.msg_EmptyClip));
          }
        });
      else
      {
        if(src.canRead()){
          if(!src.isDirectory())
          {
            try{
              BufferedInputStream in = new BufferedInputStream(new FileInputStream(src), 8192);
              BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));

              long pos = 0;
              long read = 8192;
              byte[] data = new byte[(int)read];

              while(pos<src.length()){
                int bytes = in.read(data, 0, (int)read);
                if(bytes>-1) {
                  out.write(data,0,bytes);
                  in.skip(read);
                  in.mark((int)pos+bytes);
                  in.reset();
                  dlg.incrementProgressBy(bytes);
                  pos+=bytes;
                }
              }

              Main.this.runOnUiThread(new Runnable() {
                public void run(){
                  dlg.dismiss();
                }
              });
              in.close();
              out.close();
            }catch(final Exception e)
            {
              Main.this.runOnUiThread(new Runnable() {
                public void run(){
                  alert("filePaste():\n"+e);
                }
              });
            }

            if(Moving==true) {
              boolean q = src.delete();

              if(q==true)
                Main.this.runOnUiThread(new Runnable() {
                  public void run(){
                    toast(getString(R.string.msg_MoveOK,src.getName()));
                  }
                });
              else
                Main.this.runOnUiThread(new Runnable() {
                  public void run(){
                    toast(getString(R.string.msg_MoveNO,src.getName()),1);
                  }
                });

              Moving = false;
            }
            else {
              Main.this.runOnUiThread(new Runnable() {
                public void run(){
                  toast(getString(R.string.msg_CopyOK,src.getName()));
                }
              });
            }
          }
        }
        else
          Main.this.runOnUiThread(new Runnable() {
            public void run(){
              toast(getString(R.string.msg_CopyNO,src.getName()));
            }
          });
        FileClip = null;
        Main.this.runOnUiThread(new Runnable() {
          public void run(){
            getDir(myPath.getText().toString());
          }
        });
      }
    }
  });

  dlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
  dlg.setTitle(Moving?getString(R.string.moving):getString(R.string.copying));
  dlg.setMessage(src.getName());
  dlg.setCancelable(true);
  dlg.setButton(DialogInterface.BUTTON_NEGATIVE, getString(android.R.string.cancel), new DialogInterface.OnClickListener()
  {
    @Override
    public void onClick(DialogInterface dialog, int which) {
      dlg.cancel();
    }
  });
  dlg.setOnCancelListener(new DialogInterface.OnCancelListener()
  {
    @Override
    public void onCancel(DialogInterface dialog) {
      copythread.interrupt();
      if(dest.exists())
        dest.delete();
    }
  });
  dlg.setMax((int)src.length());
  dlg.show();

  copythread.start();
}

此代码的作用是尝试复制给定文件(在FileClip中存储为字符串)。

正如您所看到的,代码很长,因为过度使用runOnUiThread。我想知道如何移动所有

Main.this.runOnUiThread(new Thread(new Runnable()
  public void run()
  {
    //Simple stuff for 6 lines
  }
));

到某个班级或某事。我在考虑

public class runAtUI implements Runnable

但我在那时停下来,我不知道如何制作施工人员。我希望你知道我的意思;类似的东西:

new runAtUI()
{
  //This makes less lines IMO, and could be executed
}

*注意:我查找了关于此的主题,但所有人都这么说,请使用runOnUiThread。我知道它没关系,但是对于一些简短的事情(比如显示一个吐司 - 使用toast()具有相同的目的 - 或者一个警告 - 获得,但是有警报() - )这是毫无意义的。

PS:这是我正在做的一个简单的文件管理器,由于缺钱而不会在Google Play上发布,我也不想使用广告(打破名称中的“简单”) )。是的,我知道有免费和无广告(这个词存在?)和更好的应用程序,但我想学习如何制作一个n_n;

任何信息,想法或指南都将受到赞赏。


编辑#2:感谢所有快速回答的问题!您提供的样品现在可以使用,但我希望它更灵活。像javascript中的eval("code as string")(没有代码是字符串)。 我会认为这个问题得到了回答,但请让人们给出更多的想法; D


编辑#3:好的,首先,抱歉很久没有回复。其次,我正在添加当前代码的链接,从123行(这一行)到pastebin的77行代码。我还要添加uithread的代码。 关于应用程序:如果您想要它进行测试,请查看它现在的情况或任何内容,给我发邮件,然后发送给您;)

3 个答案:

答案 0 :(得分:1)

您可以创建一个实用程序类来封装创建由UI线程运行并调用Toast的runnable的步骤。这是一个简单的实现:

public abstract class ToastUtils {
      /**
       * Displays a toast message, making sure that the toast is always invoked from the main (ui) thread.
       * @param act Calling Activity
       * @param text Toast text
       * @param duration Toast duration
       */
      public static void showToast(final Activity act, final String text, final int duration) {
         act.runOnUiThread(new Runnable() {
            public void run() {
               Toast.makeText(act, text, duration).show();
            }
         });
      }
   }

使用此课程,您可以在必要时进行祝酒:

ToastUtils.showToast(this,“some text”,Toast.LENGTH_SHORT);

答案 1 :(得分:0)

您可以在活动中创建Handler

Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what) {
        case R.string.cancel:
            //show toast
            break;
        default:
            break;
        }
    }
};

从你的主题中使用它:

handler.sendEmptyMessage(R.string.cancel);

答案 2 :(得分:0)

来自http://developer.android.com/guide/components/processes-and-threads.html

  

然而,随着操作的复杂性增加,这种代码   可能会变得复杂和难以维护。处理更复杂   与工作线程的交互,您可以考虑使用Handler   在您的工作线程中,处理从UI传递的消息   线。但是,最好的解决方案可能是扩展AsyncTask   class,简化了需要的工作线程任务的执行   与UI进行交互。

......跳过......

  

您可以随时在doInBackground()中调用publishProgress()   在UI线程上执行onProgressUpdate()

在我看来,这就是你想要做的事情。

关于你的另一个问题(你应该尝试每个主题只问一个问题),用Java复制文件是一个已经解决的问题。关于SO的主题,我认为这个问题有一些非常好的答案:Standard concise way to copy a file in Java?