Как обновить TextView от другого класса

Iam новое для программирования android/java. У меня есть два класса, один - это активность и другой нормальный класс. В моем классе активности есть TextView. Могу ли я обновить TextView класса активности из обычного класса. Я пробовал со случайным кодом, но он терпит неудачу. Пожалуйста, предоставьте решение...

// 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");
   }
}

Ответы

Ответ 1

Вы должны передать ссылку Context через конструктор.

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

Ответ 2

В предыдущих двух примерах TextView используется непосредственно в другом классе. Однако есть случаи, когда TextView не должен присутствовать в другом классе. например ваш класс B используется для обновления различных Деяний, где некоторые действия обновляются в TextView, другие могут быть в EditText.

Следовательно, приведенное ниже решение поможет вам разобраться в своем TextView из другого класса, но вы все равно можете достичь того, чего хотите. Он использует подход Interface.

Во-первых, объявите интерфейс, в котором у вас может быть класс B для связи с Activity, называя его MyCallBack

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

Далее в вашей деятельности реализуется MyCallBack и, следовательно, определение функции. В этой функции вы будете получать строку из класса B, чтобы вы могли делать все, что вам нравится, например. обновите TextView (или EditText и т.д.)

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

Наконец, вы можете объявить ClassB, который принимает MyCallBack (т.е. объект класса Activity, который также является MyCallBack). Оттуда вы можете использовать ClassB для связи с Activity и получить его обновление TextView через функцию 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);
}

Надеемся, что это поможет улучшить архитектуру структуры развязки свойства Activity из ClassB.

Ответ 3

Вы можете сделать метод getter в Activity.

В вашем классе Activity:

public TextView getTextView()
{

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

В вашем классе ClassB:

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

}

Ответ 4

Это на самом деле обманчиво "простой" вопрос, но на самом деле сложная проблема в контексте развития Android.

Деятельность - это "точка входа процесса", означающая, что любое действие, которое вы видите, может действовать как "первая точка входа в ваше приложение при запуске". Люди думают, что при запуске может запускаться только действие, у которого есть фильтр MAIN/LAUNCHER, но это ложь.

Любая активность может действовать как "первая активность", так как Android может перезапустить ее из любой точки с помощью текущего активного стека навигации.

В любом случае, с учетом этого, Activity может показать View, и люди часто используют Activity для хранения каждого экрана своего приложения (вместо того, чтобы использовать его как точку входа и заменять в нем контроллеры представлений ~ фрагменты).

Итак, если у вас несколько видов деятельности, вам необходимо обмениваться данными между ними таким образом, что вы принимаете это во внимание, что оба действия могут быть запущены в любое время, когда первая Активность приложения.


Для этого вам нужно не "установить текст текстового представления непосредственно из другого класса", но вам необходимо изменить наблюдаемые общие данные.

Недавно выпущенный официальный Android Architecture Components предоставляет класс LiveData<T>, который имеет подкласс под названием MutableLiveData<T>.

Чтобы обновить данные из одного класса в другой, вы должны сделать глобальные данные в виде LiveData​​p >

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

DataRepository должен выставить LiveData:

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

В случае, когда Акция подписывается на это:

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

Итак, чтобы обновить этот текст, вам нужно получить класс DataRepository и вызвать updateText на нем:

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

И это будет правильно обновлять вид вашего действия.

Ответ 5

вы можете сделать следующее. Я попробовал, и это сработало. Просто передайте ссылку на TextView при вызове метода из другого класса. Проблема в вашей версии заключается в том, что существует конфликт между TextView, потому что вы объявляете его дважды. Вместо этого объявите его только один раз и передайте его в качестве аргумента при вызове метода в другом классе. Ура!!

    // 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");
       }
    }