片段中的runOnUiThread


121

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

GoogleActivityV2来自Activity。类ExecuteTask中的runOnUiThread。类ExecuteTask嵌套在活动上。

(运行确定)现在:

GoogleActivityV2来自Fragment。类ExecuteTask中的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
    }
}

错误说: Eclipse错误

如何解决此错误?


8
您在onPostExecute中编写的代码已在主线程中运行。另一方面,您不需要调用runOnUiThread()。
rciovati 2013年

@rciovati onPostExecute的“执行操作”是不同的
Tai Dao

Answers:


271

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

这是因为:

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

2)Fragment没有runOnUiThread。

但是,Activity确实如此。

请注意,如果您已经在主线程上,则Activity仅执行Runnable,否则将使用Handler。如果您不想担心的上下文,可以Handler在片段中实现athis,这实际上非常简单:

// 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,这已经在主线程上了。


3
有时getActivity()。runOnUiThread会导致NullPointerException。你能解释一下吗?
developer1011

1
当片段从活动中分离时将发生@ developer1011。这在异步任务中很常见,因为在长时间运行的操作中该活动可能已被破坏,所以它不再存在于中get。始终首先检查null。
bclymer '16

4
谢谢。我围着它getActivity().runOnUiThreadif (isAdded())并且工作正常
developer

1
@bclymer给出的答案是Google上针对UI线程的片段中的事实上的参考,最后一部分(如何实现完成相同工作的Handler)会更详细一些!
LS97

4

在Xamarin.Android中

对于片段:

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

活动:

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

快乐编码:-)


4

使用Kotlin扩展功能

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

然后,Fragment您可以致电runOnUiThread。这样可以使活动和片段之间的呼叫保持一致。

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()
        }
    }
}

1
我绝对喜欢kotlin扩展功能。
OhhhThatVarun

2

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

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());
            }
        }
    };
}

1

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

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

根据文档:

“布尔发布(Runnable操作)导致将Runnable添加到消息队列。该runnable将在用户界面线程上运行。”

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.