2012-06-12 83 views
15

Iam新增android/java編程。我有兩個班,一個是活動和其他普通班。在我的活動類中包含TextView。我可以從普通類更新活動類的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"); 
    } 
} 
+0

我其實不想吹牛或什麼,但唯一正確的答案是我提供的:https://stackoverflow.com/questions/10996479/how-to-update-a-textview-of-an -activity-from-another-class/47637313#47637313(儘管Elye's也可以,只要他們正確地將流程中的死亡考慮在內) – EpicPandaForce

回答

38

你要通過通過構造背景下的參考。

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是一種上下文的方法嗎? – Riskhan

+0

它來自活動和視圖。 – adatapost

+1

感謝您提供解決方案 – Riskhan

3

你可以使你的Activity一個getter方法。

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

} 
+0

所述,感謝您提供的解決方案,但我與AVD – Riskhan

8

前面的兩個例子需要的TextView直接在其它類內使用。但是,有些情況下TextView不應該出現在其他類中。例如您的類B用於更新各種活動,其中一些活動在TextView上更新,其他活動可能在EditText上。

因此,下面的解決方案指導你怎麼會脫鉤其他類的TextView的,但你仍然可以達到你想要的東西。它使用接口方法。

首先聲明一個界面,你可以有B級溝通,活動,稱這是在你的活動myCallBack函數

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

下,實現myCallBack函數,因此它的功能定義。在這個函數中,你將會收到來自B類的字符串,你可以做任何你喜歡的事情,例如更新發生在myCallBack函數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的(即你的Activity類對象,它也是一個myCallBack函數)。從那裏,你可以使用ClassB的回溝通活動,並得到它更新它的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); 
} 

希望這有助於解耦從ClassB的活動性更好的架構結構。

+0

你在哪個類放置接口?謝謝 – pewpew

+1

您可以將它作爲頂級界面,也可以在ClassB中生活 – Elye

0

你可以做以下事情。我試過了,它工作。 只需在從另一個類中調用方法的同時傳入對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"); 
     } 
    } 
3

這實際上是一個看似「簡單」的問題,但實際上這是一個在Android開發環境下的複雜問題。

活動「過程入口點」,意思是你看不到任何活動可以作爲「入口的第一點您在啓動應用程序」行爲。人們認爲只有具有MAIN/LAUNCHER意圖過濾器的活動可以在啓動時啓動,但這是錯誤的。

任何活性可充當「第一活動」,因爲可以的Android從與當前激活導航堆棧的任意點重新啓動它。

無論如何,考慮到這一點,一個活動可以顯示一個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"); 

,這將正確地更新你的活動文本視圖。

+0

您可以舉一個MyData的樣子嗎? –

+0

任何Kotlin數據類或autovalue生成的值類。或者只是一些有getter/setter的字段的隨機POJO。 – EpicPandaForce

+0

好吧,我認爲我適合進入POJO,但實際上我試圖改變的價值沒有存儲對應物,因爲它是POJO現有方法的計算值,我遇到了麻煩,其中toBuilder無法解決。 –

相關問題