2012-06-12 33 views
15

Iam new to android/java programming. Tengo dos clases, una es una actividad y otra clase normal. En mi clase de actividad contiene TextView. ¿Puedo actualizar TextView de la clase de actividad de la clase normal? Intenté con un código aleatorio, pero falla. Proporcione una solución ...Cómo actualizar un TextView de una actividad de otra clase

// activity class 
public class MainMenu extends Activity { 
    public TextView txtView; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
     TextView txtView = (TextView)findViewById(R.id.text); 
    }  

} 

// other class 
public class ClassB { 
    public ClassB(){ 
    } 

    public void Update(){ 
     TextView txtView = (TextView)findViewById(R.id.text); 
     txtView.setText("Hello"); 
    } 
} 
+0

En realidad, no quiero alardear ni nada, pero la única respuesta correcta es la que proporcioné: https://stackoverflow.com/questions/10996479/how-to-update-a-textview-of-an -activity-from-another-class/47637313 # 47637313 (aunque Elye también está bien, siempre que tengan en cuenta la muerte del proceso) – EpicPandaForce

Respuesta

38

Debe pasar la referencia de contexto a través del constructor.

public class ClassB { 
    Context context; 
    public ClassB(Context context){ 
    this.context=context; 
    } 

    public void Update(){ 
     TextView txtView = (TextView) ((Activity)context).findViewById(R.id.text); 
     txtView.setText("Hello"); 
    } 
+1

¿FindViewById es un método de contexto? – Riskhan

+0

Es de actividad y vista. – adatapost

+1

gracias por proporcionar la solución – Riskhan

3

Puede realizar un método getter en su Activity.

en su clase Activity:

public TextView getTextView() 
{ 

TextView txtView = (TextView)findViewById(R.id.text); 
return txtView; 
} 

en su clase ClassB:

public void Update() 
{ 
      MainMenu obj = new MainMenu(); 
      TextView tv = obj.getTextView(); 
      tv.setText("hello"); 

} 
+0

gracias por proporcionar la solución, pero voy con AVD – Riskhan

8

Los dos ejemplos anteriores requiere TextView a utilizar directamente dentro de la otra clase. Sin embargo, hay casos donde TextView no debería estar presente en la otra clase. p.ej. su clase B se usa para actualizar varias Actividades, donde alguna actividad se actualizó en TextView, otras podrían estar en EditText.

Por lo tanto, la siguiente guía lo guiará sobre cómo puede desacoplar su TextView de otra clase, sin embargo, aún puede lograr lo que desea. Está usando el enfoque de Interfaz.

En primer lugar, declarar una interfaz donde se puede tomar la clase B para comunicar a la actividad, llamándolo MyCallback

public interface MyCallBack 
{ 
    // Declaration of the template function for the interface 
    public void UpdateMyText(String mystr); 
} 

siguiente en su actividad, implementa MyCallBack, y por lo tanto es definición de la función. En esta función, recibirás el String de la Clase B, que puedes hacer lo que quieras, p. actualizar la Vista de Texto (o EditarTexto etc ...)

public Class MyActivity extends activity implements MyCallBack; 
{ 
    // ... whatever code of your activity 

    @Overrid 
    public void UpdateMyText(String mystr) 
    { 
     TextView txtView = (TextView)findViewById(R.id.text); 
     txtView.setText(mystr); 
    } 
} 

Por último, entonces se podría declarar ClassB que lleva en MyCallBack (es decir, el objeto de la clase de actividad que es también un MyCallBack). A partir de ahí se puede utilizar para comunicarse ClassB de nuevo a la actividad y conseguir que la actualización es TextView a través de la función UpdateMyText

public class ClassB { 
    MyCallBack mCallBack = null; 
    public ClassB(MyCallBack callBack){ 
      this.mCallBack=callBack; 
    } 


    public void dosomething(){ 
     // Do something to get String 
     String myString = str; 
     this.mCallBack.UpdateMyText(str); 
} 

Esperanza esto ayuda a una mejor estructura con arquitectura de la disociación de la propiedad Actividad de ClassB.

+0

¿En qué clase colocaste la interfaz? Gracias – pewpew

+1

Podría colocarlo como una interfaz de nivel superior o podría vivir dentro de ClassB – Elye

0

puede hacer lo siguiente. Lo intenté y funcionó. Solo pase la referencia al TextView mientras llama al método desde otra clase. El problema en su versión es que hay conflicto entre TextView porque lo está declarando dos veces. En vez de declararlo solo una vez y pasarlo como un argumento al llamar al método en otra clase. ¡Saludos!

// activity class 


public class MainMenu extends Activity { 
    public TextView txtView; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
     TextView txtView = (TextView)findViewById(R.id.text); 
     ClassB.update(txtView); 
    }  

} 

    // other class 



    public class ClassB { 
     public ClassB(){ 
     } 

     public void update(TextView tv){ 
      tv.setText("Hello"); 
     } 
    } 
3

Esto es realmente una pregunta engañosamente "simple", pero en realidad es un problema complicado en el contexto del desarrollo de Android.

Las actividades son el "punto de entrada al proceso", lo que significa que cualquier actividad que vea puede actuar como el "primer punto de entrada a su aplicación en el inicio".La gente piensa que solo la Actividad que tiene el filtro de intención MAIN/LAUNCHER se puede iniciar al inicio, pero esto es falso.

Cualquier actividad puede actuar como la "primera actividad", porque Android puede reiniciarlo desde cualquier punto con la pila de navegación activa actual.

De todos modos, una Actividad puede mostrar View, y las personas a menudo usan la Actividad para mantener cada pantalla de su aplicación (en lugar de usarla como punto de entrada e intercambiar controladores de vista en ella ~ fragmentos)

Así que si usted tiene múltiples actividades, entonces usted necesita para compartir datos entre ellos de tal manera, que se toma en consideración que ambas actividades se pueden iniciar en cualquier momento como elprimeraActividad de la aplicación.


Para esto, lo que hay que hacer no es "establece el texto de la vista de texto directamente de otra clase", pero hay que modificar los datos compartidos observables.

La nueva versión oficial Android Architecture Components proporciona la clase LiveData<T>, que tiene una subclase llamada MutableLiveData<T>.

Para actualizar los datos de una clase a otra actividad, lo que debe hacer es tener un conjunto de datos globales expuestos como LiveData LiveData

public class MyApplication extends Application { 
    private static MyApplication INSTANCE; 

    DataRepository dataRepository; // this is YOUR class 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     INSTANCE = this; 
     dataRepository = new DataRepository(); 
    } 

    public static MyApplication get() { 
     return INSTANCE; 
    } 
} 

El DataRepository debe exponer:

public class DataRepository { 
    private final MutableLiveData<MyData> data = new MutableLiveData<>(); 

    public LiveData<MyData> getMyData() { 
     return data; 
    } 

    public void updateText(String text) { 
     MyData newData = data.getValue() 
          .toBuilder() // immutable new copy 
          .setText(text) 
          .build(); 
     data.setValue(newData); 
    } 
} 

Cuando el La actividad se suscribe a esto:

public class MyActivity extends AppCompatActivity { 
    DataRepository dataRepository; 

    TextView textView; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     MyApplication app = (MyApplication)getApplicationContext(); 
     dataRepository = app.getDataRepository(); 

     setContentView(R.layout.main_activity); 
     textView = findViewById(R.id.textview); 

     dataRepository.getMyData().observe(this, new Observer() { 
      @Override 
      public void onChange(MyObject myObject) { 
       textView.setText(myObject.getText()); 
      } 
     } 
    } 

Así que para actualizar esto texto, que necesita para obtener la clase DataRepository, y llamar a updateText en él:

DataRepository dataRepository = MyApplication.get().dataRepository(); 
dataRepository.updateText("my new text"); 

Y esto actualizará correctamente su vista de texto de actividad.

+0

¿Podría dar un ejemplo de cómo se vería MyData? –

+0

Cualquier clase de datos de Kotlin, o clases de valores generados de autovalor. O solo algunos POJO aleatorios con campos que tienen getters/setters. – EpicPandaForce

+0

De acuerdo, creo que encajaría en el POJO, pero realmente el valor que trato de cambiar no tiene una contraparte almacenada, ya que es un valor calculado de los métodos existentes del POJO, me estoy metiendo en problemas en los que toBuilder no puede resolver. –

Cuestiones relacionadas