runOnUiThread in Fragment


121

Ich versuche, eine Aktivität in ein Fragment umzuwandeln. Die Fehlermarkierung auf runOnUiThread. auf die Vergangenheit:

GoogleActivityV2 erstreckt sich von Aktivität. runOnUiThread in der Klasse ExecuteTask. Klasse ExecuteTask in Aktivität verschachtelt.

(Ok laufen) jetzt:

GoogleActivityV2 erstreckt sich von Fragment. runOnUiThread in der Klasse ExecuteTask. Klasse ExecuteTask in Aktivität verschachtelt. (Fehler bei runOnUiThread)

Hier ist mein Code

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

Der Fehler lautet: Eclipse-Fehler

Wie kann ich diesen Fehler beheben?


8
Der Code, den Sie in onPostExecute schreiben, wird bereits im Hauptthread ausgeführt. Auf der anderen Seite müssen Sie runOnUiThread () nicht aufrufen.
Rciovati

@rciovati "etwas tun" rein und raus auf PostExecute sind anders
Tai Dao

Antworten:


271

Versuche dies: getActivity().runOnUiThread(new Runnable...

Es ist, weil:

1) Der implizite thisAufruf Ihres Aufrufs runOnUiThreadbezieht sich auf AsyncTask, nicht auf Ihr Fragment.

2) Fragmenthat kein runOnUiThread.

Tut es Activityjedoch.

Beachten Sie, dass Activitynur ausgeführt wird, Runnablewenn Sie sich bereits im Hauptthread befinden, andernfalls wird a verwendet Handler. Sie können einHandler in Ihrem Fragment implementieren, wenn Sie sich nicht um den Kontext von kümmern möchten. thisEs ist eigentlich sehr einfach:

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

EDIT: @rciovati ist richtig, du bist dabei onPostExecute, das ist schon im Haupt-Thread.


3
Manchmal führt getActivity (). RunOnUiThread zu NullPointerException. Könntest du erklären?
Entwickler1011

1
@ developer1011, der auftritt, wenn das Fragment von der Aktivität getrennt wurde. Dies ist bei asynchronen Tasks üblich, da die Aktivität während des lang laufenden Vorgangs möglicherweise zerstört wurde und daher nicht mehr vorhanden ist get. Überprüfen Sie immer zuerst auf Null.
bclymer

4
Vielen Dank. Ich umgeben getActivity().runOnUiThreadmit if (isAdded())und es funktioniert gut
Entwickler1011

1
@bclymer Angesichts dieser Antwort handelt es sich um die De-facto-Referenz in Google für den UI-Thread in Fragmenten. Weitere Details im letzten Abschnitt (Implementieren eines Handlers, der den gleichen Job erledigt) wären nett!
LS97

4

In Xamarin.Android

Für Fragment:

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

Für Aktivität:

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

Viel Spaß beim Codieren :-)


4

Verwenden Sie eine Kotlin-Erweiterungsfunktion

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

Dann können FragmentSie in jedem einfach anrufen runOnUiThread. Dadurch bleiben Anrufe über Aktivitäten und Fragmente hinweg konsistent.

runOnUiThread {
    // Call your code here
}

HINWEIS : Wenn Fragmentkeine Verbindung mehr zu einem besteht Activity, wird kein Rückruf aufgerufen und keine Ausnahme ausgelöst

Wenn Sie von überall auf diesen Stil zugreifen möchten, können Sie ein gemeinsames Objekt hinzufügen und die Methode importieren:

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

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

1
Ich liebe Kotlin-Erweiterungsfunktionen.
OhhhThatVarun

2

Ich habe dies verwendet, um Datum und Uhrzeit in einem Fragment abzurufen.

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

Sie können Runnable auch mithilfe der Ansicht eines anderen Threads veröffentlichen. Stellen Sie jedoch sicher, dass die Ansicht nicht null ist:

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

Laut Dokumentation:

"Boolescher Beitrag (ausführbare Aktion) Bewirkt, dass die ausführbare Datei zur Nachrichtenwarteschlange hinzugefügt wird. Die ausführbare Datei wird im Thread der Benutzeroberfläche ausgeführt."

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.