runOnUiThread en fragmento

121

Estoy intentando convertir una actividad en un fragmento. La marca de error en runOnUiThread. en el pasado:

GoogleActivityV2 se extiende desde Activity. runOnUiThread en la clase ExecuteTask. clase ExecuteTask anidada en actividad.

(Ejecutar bien) ahora:

GoogleActivityV2 se extiende desde Fragment. runOnUiThread en la clase ExecuteTask. clase ExecuteTask anidada en actividad. (Error en runOnUiThread)

aquí está mi código

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

el error dice: Error de Eclipse

¿Cómo puedo solucionar este error?

Tai Dao
fuente
8
El código que escribe dentro de onPostExecute ya se ejecuta dentro del hilo principal. Por otro lado, no necesita invocar runOnUiThread ().
rciovati
@rciovati "hacer algo" dentro y fuera de PostExecute son diferentes
Tai Dao

Respuestas:

271

Prueba esto: getActivity().runOnUiThread(new Runnable...

Eso es porque:

1) lo implícito thisen su llamada a runOnUiThreadse refiere a AsyncTask, no a su fragmento.

2) Fragmentno tiene runOnUiThread.

Sin embargo, lo Activityhace.

Tenga en cuenta que Activitysolo ejecuta Runnablesi ya está en el hilo principal; de lo contrario, usa un archivo Handler. Puede implementar unHandler en su fragmento si no quiere preocuparse por el contexto de this, en realidad es muy fácil:

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

EDITAR: @rciovati tiene razón, estás dentro onPostExecute, eso ya está en el hilo principal.

bclymer
fuente
3
Algunas veces getActivity (). RunOnUiThread resulta en NullPointerException. ¿Podrías explicar?
developer1011
1
@ developer1011 que sucederá cuando el fragmento se haya separado de la actividad. Esto es común en las tareas asincrónicas, porque la actividad podría haberse destruido durante la operación de ejecución prolongada, por lo que ya no existe get. Siempre verifique si hay nulo primero.
bclymer
4
Gracias. Rodeé getActivity().runOnUiThreadcon if (isAdded())y funciona bien
developer1011
1
@bclymer dada esta respuesta es la referencia de facto en Google para el hilo de la interfaz de usuario en fragmentos, ¡sería bueno tener más detalles en la última sección (cómo implementar un controlador que hace el mismo trabajo)!
LS97
4

En Xamarin.Android

Para fragmento:

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

Para actividad:

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

Feliz codificación :-)

Ripdaman Singh
fuente
4

Usar una función de extensión de Kotlin

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

Entonces, en cualquiera Fragmentpuedes llamar runOnUiThread. Esto mantiene las llamadas consistentes en actividades y fragmentos.

runOnUiThread {
    // Call your code here
}

NOTA : Si Fragmentya no está adjunto a un Activity, no se llamará a la devolución de llamada y no se lanzará ninguna excepción.

Si desea acceder a este estilo desde cualquier lugar, puede agregar un objeto común e importar el método:

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

    fun runOnUiThread(action: () -> Unit) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            handler.post(action)
        } else {
            action.invoke()
        }
    }
}
Gibolt
fuente
1
Me encantan las funciones de extensiones de kotlin.
OhhhThatVarun
2

Usé esto para obtener la fecha y la hora en un fragmento.

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());
            }
        }
    };
}
Irving Kennedy
fuente
1

También puede publicar ejecutables usando la vista desde cualquier otro hilo. Pero asegúrese de que la vista no sea nula:

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

Según la documentación:

"publicación booleana (acción ejecutable) Hace que el ejecutable se agregue a la cola de mensajes. El ejecutable se ejecutará en el hilo de la interfaz de usuario".

Jawad Zeb
fuente