I declare a button in the Main Activity, but get NullObjectReference when I run the app. No matter where I try to move the declaration (outside of the class, inside the onCreate method, etc.), it redlines either the declaration or the button reference. I see posts recommending status versus non-static classes/methods, but I'm new to OOP and not exactly sure how to implement that. Can anyone tell me what I'm doing wrong?
public class MainActivity extends AppCompatActivity {
…
// Declare button in the MainActivity
Button btnWrong = (Button)findViewById(R.id.btnWrong);
...
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// WHEN USER TAPS ITEMS ON APPBAR
switch (item.getItemId()) {
case R.id.mnuLoad: // If use taps "Load"
final Dialog dialog = new Dialog(MainActivity.this); /
…
btnLoad.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deckNumber = deckPicker.getValue();
if … }
dialog.dismiss();
btnWrong.setEnabled(true); // Trying to reference the button here
You have to do this:
outside onCreate() (under public class MainActivity extends AppCompatActivity)
Button btnWrong; //Declare button as private
in onCreate()
btnWrong = (Button)findViewById(R.id.btnWrong);
Now you can use btnWrong anywhere in its class
Try this:
public class MainActivity extends AppCompatActivity {
// Declare as class field
Button btnWrong;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.YOUR_LAYOUT_XML);
btnWrong = (Button)findViewById(R.id.btnWrong);
}
....
}
How do i set the text of a TextView to a value of an integer from another class.
the main activity where i want the text set below
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
TextView counterText = (TextView) findViewById(R.id.counter);
counterText.setText();
}
the class below
public class Ship implements Serializable {
private static int counter = 0;
public int getCounter()
{
return counter;
}
}
For a starter this should help
Ship s=new Ship();
int i=s.getCounter();
String value=String.valueOf(i);
counterText.setText(value);
Use String.valueOf to show Integer in TextView,as:
counterText.setText(String.valueOf(new Ship().getCounter()));
As far as i know you cannot access the UI component of 2nd activity while being in first activity. So the best way is to pass the value through putExtra method of intents and then set it to textview in the onCreate of 2nd activity by getting it. Here is link which shows this method: http://mobileorchard.com/android-app-development-using-intents-to-pass-data-and-return-results-between-activities/
Assume that i have a activity class named MainActivity.java. But this activity has about 3000 lines code for example.
I want to seperate code parts of this file to an external java file(class) named NecessaryThings.java. But if i run my project on emulator it stops itself after this operation.
Is there a way to seperate some lines of this activity?
I wrote mini example for better..
Also what do you think about;
Using this method is beneficial or harmful in terms of performance?
This is my MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//I want to call these lines from NecessaryThings.java
TextView genderResult = (TextView) findViewById(R.id.genderText);
genderResult.setText("Cinsiyet:");
TextView calorieResult = (TextView) findViewById(R.id.remainCalorie);
String getGenderSTR = getIntent().getStringExtra("GENDER");
genderResult.setText(getGenderSTR);
String calorieResultSTR = getIntent().getStringExtra("CALORIECHOOSED");
calorieResult.setText(calorieResultSTR);
/*
.....
.....
*/
}
Aftet I take above code, then I want to store it in NecessaryThings.java
like this..
//All necessary imports here. There is no problem about those.
public class NecessaryThings extends Activity {
public void myPersonalMethod() {
TextView genderResult = (TextView) findViewById(R.id.genderText);
genderResult.setText("Cinsiyet:");
TextView calorieResult = (TextView) findViewById(R.id.remainCalorie);
String getGenderSTR = getIntent().getStringExtra("GENDER");
genderResult.setText(getGenderSTR);
String calorieResultSTR = getIntent().getStringExtra("CALORIECHOOSED");
calorieResult.setText(calorieResultSTR);
}
}
If I rearrange my MainActivity.java It will be like this...
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NecessaryThings showMyMethod = new NecassaryThings();
showMyMethod.myPersonalMethod();
/*
the rest of the codes...
*/
}
But it is not working if I seperate code. Why and How can I do it?
public class MainActivity extends NecessaryThings {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myPersonalMethod();
}
NecessaryThings extends Activity so MainActivity no long needs to extend from Activity, it should extend from NecessaryThings. One thing I need to point out is that super.onCreate(savedInstanceState); will call the onCreate(); from NecessaryThings. Since my myPersonalMethod(); is from super class, you can just call it.
All activities are regular Java classes and you can - of course, have many non-UI classes like Application, you can have helpers etc. Looking into your question, I would like to tell you that the Activity doesn't have user defined constructor and can be created only indirectly by calling startActivity method, but in other aspects it is a common Java class.
Hence, what you'll have to do is, let your NecessaryThings.java be a normal class, to which you can pass the context from your MainActivity and do all that is required.
Hope this helps.
public class Activity01 extends Activity implements OnClickListener,
ViewFactory {
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout main_view = new LinearLayout(this);
m_Switcher = new ImageSwitcher(this);
main_view.addView(m_Switcher);
m_Switcher.setId(SWITCHER_ID);
m_Switcher.setFactory(this);
m_Switcher.setOnClickListener(this);
setContentView(main_view);
...
}
public void onClick(View v) {
...
}
}
Above code is from an Android project, and below function's argument is set as 'this', why?
m_Switcher.setOnClickListener(this);
According to the javadoc, here should be like below:
public void setOnClickListener (View.OnClickListener l)
That means the argument should be this kind: View.OnClickListener
So why 'this' can be there? Thanks!
Note: According to the answers, I gave a more complete code above.
In the class declaration you will find it either extends or implements OnClickListener. That means that the class can be used as an OnClickListener (because it is one, amongst other things). That is why you can use this here.
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("");