Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/226.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从另一个类更新活动的TextView_Java_Android - Fatal编程技术网

Java 如何从另一个类更新活动的TextView

Java 如何从另一个类更新活动的TextView,java,android,Java,Android,我是Android/Java编程新手。我有两个班,一个是活动,另一个是普通班。我的活动类包含一个文本视图。我是否可以从普通类更新活动类的TextView?我尝试使用随机码,但失败了 // activity class public class MainMenu extends Activity { public TextView txtView; @Override public void onCreate(Bundle savedInstanceState) {

我是Android/Java编程新手。我有两个班,一个是
活动
,另一个是普通班。我的活动类包含一个
文本视图
。我是否可以从普通类更新活动类的
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");
        }
    }
}

您必须通过构造函数传递上下文引用

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

您可以在
活动中创建
getter
方法

在您的
活动中
课程:

public TextView getTextView()
{

TextView txtView = (TextView)findViewById(R.id.text);
return txtView;
}
public void Update()
{
          MainMenu obj = new MainMenu();
          TextView tv = obj.getTextView();
          tv.setText("hello");

}
在您的
ClassB
课程中:

public TextView getTextView()
{

TextView txtView = (TextView)findViewById(R.id.text);
return txtView;
}
public void Update()
{
          MainMenu obj = new MainMenu();
          TextView tv = obj.getTextView();
          tv.setText("hello");

}

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

因此,下面的解决方案可以指导您如何将
TextView
与其他类解耦,但仍然可以实现您想要的。它使用接口方法

首先,声明一个可以让
ClassB
与活动通信的接口,并将其称为
MyCallback

public interface MyCallback {
    // Declaration of the template function for the interface
    public void updateMyText(String myString);
}
接下来在活动中,实现
MyCallback
,从而实现其函数定义。在此函数中,您将从
ClassB
接收字符串,您可以执行任何您喜欢的操作,例如,更新
TextView
(或
EditText
等):

最后,您可以声明接受
MyCallback
ClassB
(即,您的活动类对象也是
MyCallback
)。从那里,您可以使用
ClassB
与Activity通信,并让Activity通过
updateMyText
功能更新其
TextView

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

正确解耦的体系结构。您可以做以下事情。我试过了,它成功了。 从另一个类调用该方法时,只需传入对TextView的引用。 您的版本中的问题是,TextView之间存在冲突,因为您声明了两次。 相反,只声明一次,并在另一个类中调用该方法时将其作为参数传递。 干杯


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

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

任何活动都可以作为“第一个活动”,因为Android可以使用当前活动导航堆栈从任何点重新启动它

无论如何,记住这一点,一个活动可以显示一个
视图
,人们通常使用该活动来保持应用程序的每个屏幕(而不是将其用作入口点,并交换其中的视图控制器)

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


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

新发布的官方版本提供了
LiveData
类,该类有一个子类称为
MutableLiveData

要将数据从一个类更新到另一个活动,必须将全局数据作为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);
    }
}
因此,要更新此文本,您需要获取
DataRepository
类,并在其上调用
updateText

DataRepository dataRepository = MyApplication.get().dataRepository();
dataRepository.updateText("my new text");
这将正确地更新活动文本视图

请注意,您还应该将数据持久化到saveInstanceState(Bundle
),这样数据就不会丢失(假设数据不是来自磁盘)

为此,您需要执行以下操作:

public class BaseActivity extends AppCompatActivity {
    DataRepository dataRepository;

    private static boolean didRestoreGlobals = false;

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

        super.onCreate(savedInstanceState);
        if(!didRestoreGlobals) {
            didRestoreGlobals = true;
            if(savedInstanceState != null) {
                dataRepository.restoreState(savedInstanceState.getBundle("dataRepository"));
            }
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle bundle) {
        super.onSaveInstanceState(bundle);
        bundle.putBundle("dataRepository", dataRepository.saveState());
    }
}

然后将
saveState/restoreState
方法相应地添加到
DataRepository

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

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

1) 活动到多个片段 下面的行可以通过FindViewById在片段类中写入


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

如果您正在activity类中创建另一个类(
ClassB
)的对象,最简单的解决方案是通过构造函数传递
TextView
如果您没有在activity类中创建对象,这个答案将没有帮助。因此,您的示例应如下所示:

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

这是访问另一布局内视图的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
//充气布局
val视图=充气(此,R.layout.ly_自定义菜单项,空)
//在充气的容器内的访问视图
val tv=view.findViewById(R.id.txtV\U WalletBalance\U侧菜单)
//设置要查看的值
tv.text=“值”
//给某物添加充气布局
我有一个XML页面(Bert.XML),其中有四个文本视图,ID分别为TextView1id、TextView2id、TextView3id和TextView4id

 <GridLayout
    android:id = "@+id/gridLayout"
    android:layout_width = "match_parent"
    android:layout_height = "wrap_content"
    android:paddingTop="10dp">

    <TextView
        android:id = "@+id/TextView1id"
        android:layout_gravity="end"
        android:hint = "@+id/Risico"
        android:textSize="@dimen/edit_size"
        android:layout_height = "wrap_content"
        android:layout_width = "fill_parent"
        android:layout_column = "0"
        android:layout_row = "1"
        android:layout_columnSpan = "3"
        />
    <TextView
        android:id = "@+id/TextView2id"
        android:layout_gravity="end"
        android:hint = "@+id/Risico"
        android:textSize="@dimen/edit_size"
        android:layout_height = "wrap_content"
        android:layout_width = "fill_parent"
        android:layout_column = "0"
        android:layout_row = "2"
        android:layout_columnSpan = "3"
        />
    <TextView
        android:id = "@+id/TextView3id"
        android:layout_gravity="end"
        android:hint = "@+id/Risico"
        android:textSize="@dimen/edit_size"
        android:layout_height = "wrap_content"
        android:layout_width = "fill_parent"
        android:layout_column = "0"
        android:layout_row = "3"
        android:layout_columnSpan = "3"
        />
    <TextView
        android:id = "@+id/TextView4id"
        android:layout_gravity="end"
        android:hint = "@+id/Risico"
        android:textSize="@dimen/edit_size"
        android:layout_height = "wrap_content"
        android:layout_width = "fill_parent"
        android:layout_column = "0"
        android:layout_row = "4"
        android:layout_columnSpan = "3"
        />

</GridLayout>
我的邮件类看起来像这样

package nl.yentel.finekinney;
import android.app.Activity;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class Mail extends AppCompatActivity {
    public String NameOfObject;
    public String KindOfObject;
    public Activity activity;

void Mail() {
    //if the name and kind has been given as an input parameter
    int ressourceId = activity.getResources().getIdentifier(NameOfObject, "id", activity.getPackageName());
    if (KindOfObject.equals("TextView")) {
        TextView TextViewObject = activity.findViewById(ressourceId); //VISArB 14
        TextViewObject.setText("this is a TextView");
    }
    if (KindOfObject.equals("EditText")) {
        EditText EditTextObject = activity.findViewById(ressourceId); //VISArB 14
        EditTextObject.setText("this is an EditText");
    }
    //if the name is hard coded
    TextView TextViewObject;
    TextViewObject = activity.findViewById(R.id.TextView3id);
    TextViewObject.setText("Hard coded ID");

    //if I want to run a method from my main Class
    Bert dezeBert = new Bert();
    dezeBert.CalculateFromClass(activity);
    }
}

findViewById是上下文方法吗?
txtView
为空。这是一个令人惊讶的不干净的解决方案。我很惊讶地看到它有这么多的投票并被接受。更好地使用如所述的接口。你能举一个例子说明MyData是什么样子的吗?任何Kotlin数据类,或autovalue生成的值类。或者只是一些带有getter/setter字段的随机POJO。@XO。我想你是经理
package nl.yentel.finekinney;
import android.app.Activity;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.TextView;

public class Bert extends AppCompatActivity {
private TextView theObject;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_bert);

        //both findViewByID work
    theObject = this.findViewById(R.id.TextView2id);
    theObject = findViewById(R.id.TextView2id);

    Mail theMail=new Mail();
    theMail.activity=this;
    theMail.NameOfObject="TextView2id";
    theMail.KindOfObject="TextView";
    theMail.Mail();

    CalculateFromClass(this);
    Calculate(this);
}
//Calculate(dezeActiviteit);
public void Calculate(Activity dezeActiviteit) {
//here you should include dezeActiviteit which can be called from the Class
    theObject = dezeActiviteit.findViewById(R.id.TextView1id);
    theObject.setText("text from method");
}
public void CalculateFromClass(Activity dezeActiviteit) {
    //here you should include dezeActiviteit which can be called from the Class
    theObject = dezeActiviteit.findViewById(R.id.TextView4id);
    theObject.setText("text from Class");
    }
}
package nl.yentel.finekinney;
import android.app.Activity;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class Mail extends AppCompatActivity {
    public String NameOfObject;
    public String KindOfObject;
    public Activity activity;

void Mail() {
    //if the name and kind has been given as an input parameter
    int ressourceId = activity.getResources().getIdentifier(NameOfObject, "id", activity.getPackageName());
    if (KindOfObject.equals("TextView")) {
        TextView TextViewObject = activity.findViewById(ressourceId); //VISArB 14
        TextViewObject.setText("this is a TextView");
    }
    if (KindOfObject.equals("EditText")) {
        EditText EditTextObject = activity.findViewById(ressourceId); //VISArB 14
        EditTextObject.setText("this is an EditText");
    }
    //if the name is hard coded
    TextView TextViewObject;
    TextViewObject = activity.findViewById(R.id.TextView3id);
    TextViewObject.setText("Hard coded ID");

    //if I want to run a method from my main Class
    Bert dezeBert = new Bert();
    dezeBert.CalculateFromClass(activity);
    }
}