I am new to Android/Java programming. I have two classes, one is an Activity and the other is a normal class. My activity class contains a TextView. Can I update the TextView of the activity class from a normal class? I tried with random code, but it fails.
// 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");
}
}
}
You have to pass the Context reference via 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");
}
The preceding two examples require TextView to be used directly within the other class. However, there are cases where TextView shouldn't be present in the other class, e.g., your ClassB is used to update various Activities, where some activities update TextViews, and others might update EditTexts.
Hence, the below solution can guide you on how you could decouple your TextView from other classes, yet, you could still achieve what you want. It's using the interface approach.
Firstly, declare an interface where you could have ClassB communicate to the Activity, and call it MyCallback:
public interface MyCallback {
// Declaration of the template function for the interface
public void updateMyText(String myString);
}
Next in your Activity, implement MyCallback, and hence its function definition. In this function, you will receive the String from ClassB that you could do whatever you like, e.g., update the TextView (or EditText, etc.):
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);
}
}
Lastly, you could declare ClassB that takes in MyCallback (i.e., your Activity class object that is also a MyCallback). From there you could use ClassB to communicate back to Activity and get it to update its TextView through the updateMyText function:
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);
}
}
}
Hope this helps better show the architected structure of decoupling the Activity properly from ClassB.
This is actually a deceptively "simple" question, but in reality a complicated problem in the context of Android development.
Activities are the "process entry point", meaning that any Activity you see can act as the "first point of entry to your application on start-up". People think that only the Activity that has the MAIN/LAUNCHER intent filter can be launched at start-up, but this is false.
Any Activity can act as the "first Activity", because Android can restart it from any point with the current active navigation stack.
Anyways, with that in mind, an Activity can show a View, and people often use the Activity to hold each screen of their app (instead of using it as an entry point, and swapping out view controllers in it ~ fragments).
So if you have multiple Activities, then you need to share data between them in such a way, that you take it into consideration that both activities can be started up at any time as the first Activity of the app.
For this, what you need to do is not "set the text view's text directly from another class", but you need to modify observable shared data.
The newly released official Android Architecture Components provide the LiveData<T> class, which has a subclass called MutableLiveData<T>.
To update the data from one class to another Activity, what you must do is have a global data exposed as a 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;
}
}
The DataRepository should expose 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);
}
}
Where the Activity subscribes to this:
public class MyActivity extends BaseActivity {
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());
}
}
}
So to update this text, you need to get the DataRepository class, and call updateText on it:
DataRepository dataRepository = MyApplication.get().dataRepository();
dataRepository.updateText("my new text");
And this will properly update your Activity text view.
Beware that you should also persist the data to onSaveInstanceState(Bundle so that it is not lost (assuming the data is not from disk).
To do that, you need to do the following:
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());
}
}
And then add saveState/restoreState methods to DataRepository accordingly.
If you are creating an object of your other class(ClassB)inside activity class, the simplest solution is to pass the TextView through constructor (if you aren't create an object in the activity class this answer will not be helpful). So your example should be like below:
// 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");
}
}
You can make a getter method in your Activity.
In your Activity class:
public TextView getTextView()
{
TextView txtView = (TextView)findViewById(R.id.text);
return txtView;
}
In your ClassB class:
public void Update()
{
MainMenu obj = new MainMenu();
TextView tv = obj.getTextView();
tv.setText("hello");
}
I have a XML page (Bert.XML) with four TextViews with ID's TextView1id, TextView2id, TextView3id and 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>
The code for this view is shown below. In here I change the text of the TextViews through the Mail Class. The Activity has been given as a parameter for the Mail Class
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");
}
}
My Mail Class looks like this
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);
}
}
This is kotlin code to access the view inside another layout :
//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
you can do the following thing. I tried it and it worked.
Just pass in the reference to the TextView while calling the method from another class.
The problem in your version, is that there is conflict between TextView because you are declaring it twice.
Instead declare it only once and pass it as an argument while calling the method in another class.
Cheers!!
// 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");
}
}
This can be manage easily in simple to steps.
================================
1) Activity to Multiple Fragment
below line can write in Fragment class Via FindViewById
((TextView) ((Activity) getActivity()).findViewById(R.id.textview)).setText("");
Related
I have recyclerview with each item holding some buttons and text.
I am setting my onViewClickListener in the ViewHolder. I have a Room database initialized in the MainActivity.
In terms of good app architecture, how should I change the data in my database once my OnClickListener triggers?
Do I pass the database as a parameter to the adapter then the view holder?
OR
Do I get the database through a getDatabase method that I implement?
What is the best way to go about this? I am open to any suggestion/design pattern.
How is something like this generally handled?
Best practise is to keep the database in your AppCompatActivity.
If you display database data in that recyclerView you should create an ArrayList filled with those data and pass it to the recyclerViewAdapter in the constructor like MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(myData)
Then everytime you change something from that list (from your activity) you just call notify method based on your action. General one is myRecyclerViewAdapter.notifyDataSetChanged(). But with lot data it's more efficient to use more specific notify methods.
And if the database should change based on some event in recyclerView, for example by the onViewClickListener. You should create an interface in which you would pass the change and then apply the change to the database in your AppCompatActivity.
You should keep your database (and strongly advise you to use the data with ViewModel) in your activity. You can make changes on data of recyclerview item by using weakreference and interface. Here is example of activity and adapter.
public class MyActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private MyObjectAdapter adapter;
private final List<MyObject> myObjectList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
//define your views here..
setAdapter();
getData();
}
private void setAdapter(){
adapter = new MyObjectAdapter(myObjectList, new
MyObjectAdapter.IObjectClickListener() {
#Override
public void onButtonOneClick(MyObject myObject) {
//do button one operation with object item;
}
#Override
public void onButtonTwoClick(MyObject myObject) {
//do button two operation with object item;
}
});
}
private void getData(){
//Get your data from database and pass add them all into our
//myObjectList
myObjectList.addAll(objects); //Suppose objects come from database
adapter.notifyDataSetChanged();
}
}
And adapter class is like
public class MyObjectAdapter extends RecyclerView.Adapter<MyObjectAdapter.ObjectViewHolder> {
private final List<MyObject> myObjects;
private final IObjectClickListener listener; //defined at the bottom
public MyObjectAdapter(List<MyObject> myObjects, IObjectClickListener listener) {
this.myObjects = myObjects;
this.listener = listener;
}
/*
..
Other methods of adapter are here
..
*/
public class ObjectViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private Button buttonOne, buttonTwo;
private WeakReference<IObjectClickListener> reference;
public ObjectViewHolder(#NonNull View itemView) {
super(itemView);
//define your views here
reference = new WeakReference<>(listener);
buttonOne.setOnClickListener(this);
buttonTwo.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v == buttonOne){
reference.get().onButtonOneClick(myObjects.get(getAdapterPosition()));
} else if (v == buttonTwo){
reference.get().onButtonTwoClick(myObjects.get(getAdapterPosition()));
}
}
public interface IObjectClickListener{
void onButtonOneClick(MyObject myObject);
void onButtonTwoClick(MyObject myObject);
}
}
I have created an volley list in this i have problem to get data from adapter to activity and this activity to another activity. I have received error cannot cast activity.java to anotherActivity.java below is my code. Please help me anyone thanks.
My Interface itemclick in Adapter class
private OnItemClickGetPlaylist mListener;
public interface OnItemClickGetPlaylist{
public void OnPlaylistItemClick(String playlistName,int numOfItems,String imageViewForPlaylist);
}
public void setOnClickListenerOnPlaylist(OnItemClickGetPlaylist listener)
{
mListener = listener;
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id = playlist.getId_playlist_identify();
String PlaylistName = playlist.getTitile_of_playlist();
String imageOfPlaylist = playlist.getImage_of_playlist();
int numOfPlaylistSongs = getItemCount();
SendIdToDatabase(id);
if (mListener != null)
{
mListener.OnPlaylistItemClick(PlaylistName,numOfPlaylistSongs,imageOfPlaylist);
}
else {
Toast.makeText(context, "mListeren is null" + mListener, Toast.LENGTH_SHORT).show();
}
}
});
After get data handle OnPlaylistItemClick click in Activity below Codes
public void OnItemClickHandleInPlaylistActivity(String playlistName,int numOfItems,String imageViewForPlaylist)
{
//here is the adapter item click in activity now i want to send that data to another activity without any intent please help me.
// i have implement below code but it give me cannot cast activity to another activity error.
((anotherActivity) getApplicationContext()).OnItemClickInMusicActivity(playlistName,numOfItems,imageViewForPlaylist);
}
See the solution at https://stackoverflow.com/a/47637313/2413303
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;
}
}
The DataRepository should expose 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);
}
}
Where the Activity subscribes to this:
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());
}
}
}
So to update this text, you need to get the DataRepository class, and call updateText on it:
DataRepository dataRepository = MyApplication.get().dataRepository();
dataRepository.updateText("my new text");
Make sure that the data in DataRepository is properly persisted somewhere, or at least can be obtained again after process death. You might want to use a database for example (but not shared preferences).
If you don't want to use Intents, maybe you can use a publish/subscribe architecture. There is a library called eventbus (org.greenrobot:eventbus) very easy to use which could achieve what you want.
Use an Application Class instead.
public class MyApplicationClass extends Application{
#Override
public void onCreate() {
super.onCreate();
///do something on create
}
getterMethods(){...}
setterMethods(){...}
}
then add android:name=".MyApplicationClass" to manifest file
Now you can access the methods in class by
MyApplicationClass applicationClass = (MyApplicationClass)getApplicationContext();
int id = applicationClass .getterMethod().getID;
String playListName = applicationClass .getterMethod().getPlayListName();
and vice versa for Setter();
after that you can use it for data getting and setting Data throughout the application.
Hope it helps :)
References:
https://guides.codepath.com/android/Understanding-the-Android-Application-Class
I find the best to use callbacks.
in ClassA:
Create interface
MyCallback callback;
viod setCallback(MyCallback callback){
this.callback = callback;
}
viod onStop(){
callback = null;
}
interface MyCallback{
void doSomething(Params params);
}
in ClassB:
implement MyCallback
public class ClassB **implements ClassA.MyCallback**
set reference in onCreate
ClassA classA = new ClassA();
classA.setCallback(this);
// override method doSomething
#override
void doSomething(Params params){
//do your thing with the params…
}
when the job is done inside class A call:
callback.doSomething(params);
destroy reference inside class B in onStop()
classA.onStop();
So There are 3 activities A, B and C.
From Activity A, I go to activity B in activity B, I perform some tasks and I go to Activity C from Activity B.
I activity C, I have a button and some data, when I click the button I should update text in activity A. Is there a best way to do it?
edit: I do not want to go to back, when I click the button in activity C, but the text present in the activity a should be updated, later when I reach the activity a I should see the changes.
I think, you should create a separate class that you will share between your activities A, B and C. The class should has a field, which will store text for your TextView in activity A. And there is a good variant to use Observer pattern (rxJava or custom decision).
Example:
SharedStateModel is used to save state for ActivityA.
That decision is not very clear, because it breaks dependency inversion rule so I recommend you to use Dagger 2 to inject SharedStateModel into ActivityA and ActivityC and manage its component's lifecycle like I describe in comments to SharedStateModeClass.
/*
Let's make that state-class a local singleton - you create it in onCreate of ActivityA and
further it can be destroyed in onDestroy of ActivityA.
*/
public class SharedStateModel {
private PublishSubject<String> stateListener = PublishSubject.create();
private String viewState;
private static SharedStateModel instance;
private SharedStateModel() {
}
public void setViewState(String viewState) {
this.viewState = viewState;
stateListener.onNext(viewState);
}
public PublishSubject<String> getStateListener() {
return stateListener;
}
public void destroyViewState() {
instance = null;
}
public static SharedStateModel getInstance() {
if (instance != null) {
return instance;
} else {
instance = new SharedStateModel();
return instance;
}
}
}
public class ActivityA extends AppCompatActivity {
#BindView(R.id.textView)
private TextView textView;
private SharedStateModel sharedStateModel;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
sharedStateModel = SharedStateModel.getInstance();
sharedStateModel.getStateListener().subscribe(
textViewState -> textView.setText(textViewState));
}
#Override
protected void onDestroy() {
super.onDestroy();
sharedStateModel.destroyViewState();
}
}
public class ActivityC extends AppCompatActivity {
#BindView(R.id.button)
private Button button;
/*
Let's assume that you want to send a message from EditText in ActivityC
*/
#BindView(R.id.editText)
private EditText editText;
private SharedStateModel sharedStateModel;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
sharedStateModel = SharedStateModel.getInstance();
button.setOnClickListener(view -> sharedStateModel.setViewState(
String.valueOf(editText.getText().toString())));
}
}
And I want to recommend you good guides from Eugene Matsyuk if you want to learn Dagger 2.
2 way
when you leaving activity C and going to activity A, pass the value from activity C to A just like you are going to a new activity. then set the text view.
Pass your textView object from activity A activity B, then activity B to activity C. in activity C just setText normally with the textview object you bring from activity A to activity C.
I have a main activity class which instantiates the variables for my widgets and makes references to them with findViewById. I would like to be able to set the text on a textview from a separate class, however eclipse complains that the variables cannot be resolved. I have set the main activity widget variables to public. Sorry if this is a silly question, I'm new to android.
public class MainActivity extends Activity {
public TextView player1ScoreView;
public TextView player2ScoreView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
player1ScoreView = (TextView) findViewById(R.id.player1ScoreTextView);
player2ScoreView = (TextView) findViewById(R.id.player2ScoreTextView);
}
}
public class GamePlay {
...
player1ScoreView.setText(num.format(player1score));
}
player1ScoreView isn't recognized in the separate class. Does GamePlay have to be an activity to be able to set the text on a widget? Please explain. Thanks in advance
Your instance of the GamePlay class must have a reference to your MainActivity object in oder to access its members.
public class GamePlay {
...
MainActivity main = ...
....
main.player1ScoreView.setText(num.format(player1score));
}
Of course it would be better to access is via a getter method.
I'm not sure how you'll pass the reference of the MainActivity to your GamePlay object. It depends on how you create that object.
You would need to send an instance of the TextView to the other class or return the value to set and set it in the Activity.
So, you could get an instance of that class then send the TextView to a method of that class and set it there.
gamePlay.setScore(player1ScoreView);
and in the class
public void setScore(TextView tv)
{
tv.setText(num.formatplayer1score);
}
Or get the text to set from the gameplay class with something like
player1scoreview.setText(gameplay.getScore());
then have a method getScore() in your GamePlay class which would return a String to set the text as.
Simple option is to pass TextView object(player1ScoreView) as a parameter in GamePlay class method. By passing this object you can set value for this object through this method of GamePlay class.
Refer code below:
public class MainActivity extends Activity {
public TextView player1ScoreView;
public TextView player2ScoreView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
player1ScoreView = (TextView) findViewById(R.id.player1ScoreTextView);
player2ScoreView = (TextView) findViewById(R.id.player2ScoreTextView);
GamePlay gamePlay=new GamePlay();
gamePlay.setViewValue(player2ScoreView);
}
}
public class GamePlay {
...
public void setViewValue(TextView player2ScoreView)
{
player2ScoreView.setText(num.format(player1score));
}
}
I'm trying to pass something from one class to my MainActivity, but it doesn't seem to work, I don't understand why.
I have my GPS Tracker on another class (not the MainActivity) in order to reuse it.
When the location changes, I want my other class to call a method from within the MainActivity to update my UI.
I summarized my code like that :
My MAIN ACTIVITY :
public class MainActivity extends Activity implements OnClickListener {
TextView tv;
EditText et;
Button btun;
int arg0;
int stuff;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
et = (EditText) findViewById(R.id.et);
btun = (Button) findViewById(R.id.btun);
btun.setOnClickListener(this);
}
private void setter(int stuff) {
tv.setText(stuff);
}
public void setText(int _stuff) {
_stuff = stuff;
setter(_stuff);
}
#Override
public void onClick(View v) {
Getter get = new Getter();
get.getInfo(Integer.parseInt(et.getText().toString()));
}
The other Class :
public class Getter {
int _getString;
MainActivity main = new MainActivity();
public void getInfo(int getString) {
_getString = getString * 8;
main.setText(_getString);
}
}
I end up having a NullPointerException in my LogCat
at :
- tv.setText(stuff);
- setter(_stuff);
- main.setText(_getString);
- get.getInfo(Integer.parseInt(et.getText().toString()));
and I don't really know why, and above all, how to fix it.
I'll appreciate any help !
(PS : My GPS tracker thingy is working fine, it's just about invoking my setter() method.
Instantiaing an Object of MainActivity doesn't automatically call onCreate method but this method is called when you start an activity using Intent; And using the same intent you can pass extra values. For example:
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra("key", value);
context.startActivity(intent);
and then in your main activity onCreate method:
String value = getIntent.getStringExtra("key");
Edit:
In your case why don't you change your void getInfo(int getString) to return a String value i.e.
public class Getter {
...
...
public String getInfo(int getString) {
_getString = getString * 8;
return Integer.toString(_getString);
}
}
and then in onClick event of MainActivity bind this returned text to TextView
It's maybe because the MainActivity's onCreate()-Method hasn't been called. Therefore the tv is still null causing the NullPointerException
One problem is here. main is an Activity, but it should be the MainActivity calling this object.
public class Getter {
int _getString;
MainActivity main = new MainActivity();
public void getInfo(int getString) {
_getString = getString * 8;
main.setText(_getString);
}
}
I cannot really make out what you are trying to achieve in the Getter class, but either:
1: Pass the Activity instance to the object
public class Getter {
int _getString;
MainActivity _main = null;
public Getter(MainActivity main) {
_main = main;
}
public void getInfo(int getString) {
_getString = getString * 8;
_main.setText(_getString);
}
}
#Override
public void onClick(View v) {
Getter get = new Getter(this);
get.getInfo(Integer.parseInt(et.getText().toString()));
}
or
2: set the text in the Activity and only get the value from the Getter (My choice)
public class Getter {
int _getString;
MainActivity main = new MainActivity();
public void getInfo(int getString) {
return getString * 8;
}
}
#Override
public void onClick(View v) {
Getter get = new Getter();
int info = get.getInfo(Integer.parseInt(et.getText().toString()));
setText(Integer.toString(info));
}
Use Application Class or create a separate Class and declare a static variable in it. Use getter & setter methods to get the value. To update the Textview in mainacivity from other class pass the texview reference variable from main activity and put null check condition in other class if textview is not null then update the value.