【问题标题】:runOnUiThread in fragment片段中的 runOnUiThread
【发布时间】:2013-05-01 18:24:12
【问题描述】:

我正在尝试将 Activity 转换为片段。 runOnUiThread 上的错误标记。 关于过去:

GoogleActivityV2 从 Activity 扩展而来。类中的 runOnUiThread 执行任务。类 ExecuteTask 嵌套在活动中。

(运行正常) 现在:

GoogleActivityV2 从 Fragment 扩展而来。类中的 runOnUiThread 执行任务。类 ExecuteTask 嵌套在活动上。 (错误开启 runOnUiThread)

这是我的代码

public class GoogleActivityV2 extends SherlockMapFragment implements OnMapClickListener , OnMapLongClickListener , OnCameraChangeListener , TextWatcher {


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        View rootView = inflater.inflate(R.layout.activity_googlev2, container, false);
        Init();
        adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_dropdown_item_1line);
        textView = (AutoCompleteTextView) getView().findViewById(R.id.autoCompleteTextView1);
        return rootView;
    }

    public void onCameraChange(CameraPosition arg0){
        // TODO Auto-generated method stub
    }

    public void onMapLongClick(LatLng arg0){
        llLoc = arg0;
        stCommand = "onTouchEvent";
        lp = new ExecuteTask();
        lp.execute();
    }

    public void onMapClick(LatLng arg0){
        // TODO Auto-generated method stub
    }

    class ExecuteTask extends AsyncTask<String, String, String> {
        @Override
        protected void onPreExecute(){
            super.onPreExecute();
            if(stCommand.compareTo("AutoCompleteTextView") != 0) {
                pDialog = new ProgressDialog(getActivity());
                pDialog.setMessage(Html.fromHtml("<b>Search</b><br/>Loading ..."));
                pDialog.setIndeterminate(false);
                pDialog.setCancelable(false);
                pDialog.show();
            }
        }

        protected String doInBackground(String ... args){
            do something
            return null;
        }

        @Override
        protected void onPostExecute(String file_url){
            if(stCommand.compareTo("AutoCompleteTextView") != 0) pDialog.dismiss();
            runOnUiThread(new Runnable() {
                public void run(){
                    do something
                }
            });
        }
    }
    public void afterTextChanged(Editable s){
        // TODO Auto-generated method stub
    }

    public void beforeTextChanged(CharSequence s, int start, int count, int after){
        // TODO Auto-generated method stub
    }

    public void onTextChanged(CharSequence s, int start, int before, int count){
        // TODO Auto-generated method stub
    }
}

错误说:

我该如何解决这个错误?

【问题讨论】:

  • 您在 onPostExecute 中编写的代码已经在主线程中运行。另一方面,您不需要调用 runOnUiThread()。
  • @rciovati "do something" 进出 onPostExecute 是不同的

标签: android android-fragments android-activity


【解决方案1】:

试试这个:getActivity().runOnUiThread(new Runnable...

因为:

1) 您对runOnUiThread 的调用中隐含的this 指的是AsyncTask,而不是您的片段。

2) Fragment doesn't have runOnUiThread.

However, Activity does.

请注意,Activity 仅在您已经在主线程上时执行Runnable,否则它使用HandlerYou can implement a Handler 在你的片段中如果你不想担心this 的上下文,其实很简单:

// A class instance
private Handler mHandler = new Handler(Looper.getMainLooper());

// anywhere else in your code
mHandler.post(<your runnable>);
// ^ this will always be run on the next run loop on the main thread.

编辑:@rciovati 是对的,你在 onPostExecute,这已经在主线程上。

【讨论】:

  • 有时 getActivity().runOnUiThread 会导致 NullPointerException。你能解释一下吗?
  • @developer1011 将在片段与活动分离时发生。这在异步任务中很常见,因为活动可能在长时间运行的操作期间被破坏,因此它不再存在于get。始终首先检查 null。
  • 谢谢。我用if (isAdded())包围了getActivity().runOnUiThread,它工作正常
  • @bclymer 给出的这个答案是 Google 上关于片段中 UI 线程的事实上的参考,最后一部分的更多细节(如何实现完成相同工作的处理程序)会很好!
【解决方案2】:

在 Xamarin.Android 中

对于片段:

this.Activity.RunOnUiThread(() => { yourtextbox.Text="Hello"; });

对于活动:

RunOnUiThread(() => { yourtextbox.Text="Hello"; });

编码愉快 :-)

【讨论】:

    【解决方案3】:

    我用它来获取片段中的日期和时间。

    private Handler mHandler = new Handler(Looper.getMainLooper());
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    
        // Inflate the layout for this fragment
        View root = inflater.inflate(R.layout.fragment_head_screen, container, false);
    
        dateTextView =  root.findViewById(R.id.dateView);
        hourTv = root.findViewById(R.id.hourView);
    
            Thread thread = new Thread() {
            @Override
            public void run() {
                try {
                    while (!isInterrupted()) {
                        Thread.sleep(1000);
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                //Calendario para obtener fecha & hora
                                Date currentTime = Calendar.getInstance().getTime();
                                SimpleDateFormat date_sdf = new SimpleDateFormat("dd/MM/yyyy");
                                SimpleDateFormat hour_sdf = new SimpleDateFormat("HH:mm a");
    
                                String currentDate = date_sdf.format(currentTime);
                                String currentHour = hour_sdf.format(currentTime);
    
                                dateTextView.setText(currentDate);
                                hourTv.setText(currentHour);
                            }
                        });
                    }
                } catch (InterruptedException e) {
                    Log.v("InterruptedException", e.getMessage());
                }
            }
        };
    }
    

    【讨论】:

      【解决方案4】:

      您还可以使用来自任何其他线程的视图发布可运行文件。但请确保视图不为空:

       tView.post(new Runnable() {
                          @Override
                          public void run() {
                              tView.setText("Success");
                          }
                      });
      

      根据文档:

      "布尔型帖子(可运行动作) 使 Runnable 添加到消息队列中。可运行对象将在用户界面线程上运行。”

      【讨论】:

        【解决方案5】:

        使用 Kotlin 扩展函数

        fun Fragment?.runOnUiThread(action: () -> Unit) {
            this ?: return
            if (!isAdded) return // Fragment not attached to an Activity
            activity?.runOnUiThread(action)
        }
        

        然后,在任何Fragment 中,您都可以调用runOnUiThread。这样可以使 Activity 和 Fragment 之间的调用保持一致。

        runOnUiThread {
            // Call your code here
        }
        

        注意:如果Fragment 不再附加到Activity,则不会调用回调并且不会抛出异常

        如果你想从任何地方访问这个样式,你可以添加一个通用对象并导入方法:

        object ThreadUtil {
            private val handler = Handler(Looper.getMainLooper())
        
            fun runOnUiThread(action: () -> Unit) {
                if (Looper.myLooper() != Looper.getMainLooper()) {
                    handler.post(action)
                } else {
                    action.invoke()
                }
            }
        }
        

        【讨论】:

        • 我非常喜欢 kotlin 扩展功能。
        【解决方案6】:

        对于片段上的 Kotlin,只需执行此操作

        activity?.runOnUiThread(Runnable {
                //on main thread
            })
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-14
          • 2015-06-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多