如何从另一个类更新Activity的TextView

问题描述 投票:25回答:8

我是Android / Java编程的新手。我有两个班,一个是Activity,另一个是普通班。我的活动类包含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");
        }
    }
}
java android
8个回答
51
投票

您必须通过构造函数传递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");
   }

20
投票

前面两个例子要求TextView直接在另一个类中使用。但是,有些情况下TextView不应出现在另一类中,例如,您的ClassB用于更新各种活动,其中一些活动更新TextViews,而其他活动可能更新EditTexts。

因此,以下解决方案可以指导您如何将TextView与其他课程分离,但是,您仍然可以达到您想要的效果。它正在使用接口方法。

首先,声明一个接口,你可以让ClassB与Activity通信,并称之为MyCallback

public interface MyCallback {
    // Declaration of the template function for the interface
    public void updateMyText(String myString);
}

接下来在您的Activity中,实现MyCallback,从而实现其函数定义。在这个函数中,你将收到来自ClassB的字符串,你可以做任何你喜欢的事情,例如,更新TextView(或EditText等):

public class MyActivity extends AppCompatActivity implements MyCallback {
    // ... whatever code of your activity

    @Override
    public void updateMyText(String myString) {
        ((TextView)findViewById(R.id.text)).setText(myString);
    }
}

最后,你可以声明ClassB接受MyCallback(即你的Activity类对象也是MyCallback)。从那里你可以使用ClassB回复到Activity并让它通过TextView函数更新它的updateMyText

public class ClassB {
    MyCallback myCallback = null;

    public ClassB(MyCallback callback) {
        this.myCallback = callback;
    }

    public void doSomething() {
        // Do something to get String
        String myString = str;

        if (myCallback != null) {
            myCallback.updateMyText(myString);
        }
    }
}

希望这有助于更好地展示从ClassB正确解耦活动的架构结构。


10
投票

这实际上是一个看似“简单”的问题,但实际上是Android开发环境中的一个复杂问题。

活动是“流程入口点”,这意味着您看到的任何活动都可以作为“启动时应用程序的第一个入口点”。人们认为只有具有MAIN/LAUNCHER意图过滤器的Activity才能在启动时启动,但这是错误的。

任何Activity都可以充当“第一个Activity”,因为Android可以从具有当前活动导航堆栈的任何点重新启动它。

无论如何,考虑到这一点,一个Activity可以显示一个View,并且人们经常使用Activity来保存他们的应用程序的每个屏幕(而不是使用它作为入口点,并交换其中的视图控制器〜片段)。

因此,如果您有多个活动,那么您需要以这样的方式在它们之间共享数据,您需要考虑这两个活动可以随时作为应用程序的第一个活动启动。


为此,您需要做的不是“直接从另一个类设置文本视图的文本”,但您需要修改可观察的共享数据。

最新发布的官方Android Architecture Components提供了LiveData<T>类,它有一个名为MutableLiveData<T>的子类。

要将数据从一个类更新到另一个类,您必须做的是将全局数据公开为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;
    }
}

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

这将正确更新您的活动文本视图。

请注意,您还应该将数据保存到onSaveInstanceState(Bundle,以便它不会丢失(假设数据不是来自磁盘)


2
投票

你可以在你的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");

}

1
投票

如果要在活动类中创建其他类(ClassB)的对象,最简单的解决方案是通过构造函数传递TextView(如果您不在活动类中创建对象,则此答案将没有帮助)。所以你的例子应该如下:

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

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        txtView = (TextView)findViewById(R.id.text);
        //instantiating a object of the ClassB and passing tv
        ClassB obj = new ClassB(txtView);
    }    

}

// other class
public class ClassB {
   //declarre tv
   TextView txtView;

   //get the tv as arg
   public ClassB(TextView tv){
        txtView = tv;
   }

   public void Update(){
        txtView.setText("Hello");
   }
}

0
投票

这是用于访问另一个布局内的视图的kotlin代码:

//inflate layout
  val view = inflate(this, R.layout.ly_custom_menu_item, null)
//access view inside the inflated    
val tv = view.findViewById<AppCompatTextView>(R.id.txtV_WalletBalance_SideMenu)
//set value to view
 tv.text = "Value"
//Add inflated Layout to something

-1
投票

你可以做以下事情。我尝试了它,它的工作原理。只需从另一个类调用该方法时传入对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");
       }
    }

-1
投票

这可以通过简单的步骤轻松管理。

================================

1) Activity to Multiple Fragment

下面的行可以通过FindViewById写入Fragment类

((TextView)((Activity)getActivity())。findViewById(R.id.textview))。setText(“”);

© www.soinside.com 2019 - 2024. All rights reserved.