runOnUiThread trong phân đoạn


121

Tôi đang cố gắng chuyển đổi Hoạt động thành phân mảnh. Dấu lỗi trên runOnUiThread. trong quá khứ:

GoogleActivityV2 mở rộng từ Hoạt động. runOnUiThread trong lớp ExecuteTask. lớp ExecuteTask lồng vào hoạt động.

(Chạy ok) ngay bây giờ:

GoogleActivityV2 mở rộng từ Fragment. runOnUiThread trong lớp ExecuteTask. lớp ExecuteTask lồng vào hoạt động. (Lỗi trên runOnUiThread)

đây là mã của tôi

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

lỗi nói: Lỗi Eclipse

làm cách nào để sửa lỗi này


8
Mã bạn viết bên trong onPostExecute đã chạy bên trong luồng chính. Mặt khác, bạn không cần phải lập hóa đơn runOnUiThread ().
rciovati

@rciovati "do something" trong và ngoài onPostExecute là khác nhau
Tai Dao

Câu trả lời:


271

Thử cái này: getActivity().runOnUiThread(new Runnable...

Là vì:

1) hàm ý thistrong lời gọi của bạn runOnUiThreadlà đề cập đến AsyncTask, không phải phân đoạn của bạn.

2) Fragmentkhông có runOnUiThread.

Tuy nhiên, Activitykhông.

Lưu ý rằng Activitychỉ thực thi Runnablenếu bạn đã ở trên luồng chính, nếu không nó sử dụng a Handler. Bạn có thể triển khai mộtHandler trong phân đoạn của mình nếu bạn không muốn lo lắng về bối cảnh của this, nó thực sự rất dễ dàng:

// 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.

CHỈNH SỬA: @rciovati đã đúng, bạn đã tham gia onPostExecute, điều đó đã có trên chủ đề chính.


3
Đôi khi getActivity (). RunOnUiThread dẫn đến NullPointerException. Bạn có thể giải thích?
developer1011,

1
@ developer1011 điều đó sẽ xảy ra khi phân đoạn đã được tách ra khỏi hoạt động. Điều này thường xảy ra trong các tác vụ không đồng bộ, bởi vì hoạt động có thể đã bị phá hủy trong quá trình hoạt động lâu dài, vì vậy nó không còn tồn tại get. Luôn luôn kiểm tra null trước.
bclymer

4
Cảm ơn. Tôi đã bao quanh getActivity().runOnUiThreadvới if (isAdded())và nó hoạt động tốt
nhà phát

1
@bclymer đưa ra câu trả lời này là tài liệu tham khảo trên thực tế trên Google cho chuỗi giao diện người dùng ở dạng phân đoạn, một số chi tiết hơn trong phần cuối cùng (cách triển khai Trình xử lý hoàn thành công việc tương tự) sẽ rất hay!
LS97

4

Trong Xamarin.Android

Đối với Fragment:

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

Đối với hoạt động:

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

Chúc bạn viết mã vui vẻ :-)


4

Sử dụng chức năng mở rộng Kotlin

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

Sau đó, Fragmentbạn có thể gọi bất kỳ runOnUiThread. Điều này giữ cho các cuộc gọi nhất quán giữa các hoạt động và các phân đoạn.

runOnUiThread {
    // Call your code here
}

LƯU Ý : Nếu Fragmentkhông còn được gắn với một Activity, lệnh gọi lại sẽ không được gọi và không có ngoại lệ nào được ném ra

Nếu bạn muốn truy cập kiểu này từ bất kỳ đâu, bạn có thể thêm một đối tượng chung và nhập phương thức:

object ThreadUtil {
    private val handler = Handler(Looper.getMainLooper())

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

1
Tôi hoàn toàn thích các chức năng mở rộng kotlin.
OhhhThatVarun

2

Tôi đã sử dụng điều này để lấy Ngày và Giờ trong một phân đoạn.

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

Bạn cũng có thể đăng có thể chạy bằng cách sử dụng chế độ xem từ bất kỳ chuỗi nào khác. Nhưng hãy chắc chắn rằng chế độ xem không rỗng:

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

Theo Tài liệu:

"boolean post (Runnable action) Khiến Runnable được thêm vào hàng đợi tin nhắn. Runnable sẽ được chạy trên chuỗi giao diện người dùng."

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.