Android/Java: Change view from another class? - android

There are two classes. MainActivity, in which i set the view, and ClassX from which i want to update a view in MainActivity. ClassX is an AsyncTask called from MainActivity, if that's relevant.
What i want to do is to change the text of a view called mainTextLog. I've declared a global TextView variable, and in the onCreate() method i set it to the view using findViewById().
private TextView logger;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
logger = (TextView) findViewById(R.id.mainTextLog);
}
By now i should be able to change the text from onCreate(), and i can. But since i want to change it from another class (ClassX) i need to create a method for it:
public void setLogText(String text) {
logger.setText(text);
}
But it doesn't work. I've tried making logger and the setLogText() method static, but it still doesn't work. The app just crashes.
It's probably pretty easy, but i'm out of ideas.

If you are using an AsyncTask you need to set the value in either onProgressUpdate or in onPostExecute.
You really should read the documentation for AsyncTasks
You CANNOT update the UI from the doInBackground method as it is not run in the UI thread and will give you an exception.
Also, you should post the exception you are getting when the application crashes so we have a better idea what the problem is. But I'd guess you are trying to update the text from the wrong thread.

I've done this plenty in the app im working on, its sort of an MDI type app on the android tablet.
To do what you're asking....
in MainActivity have
public static void setText(String txt){
((TextView)findViewById(R.id.mainTextLog)).setText(txt);
}
then in the child (or calling class) call it like...
MainActivity.setText("myTextToShow");
That's it... im using android api level 12... If i remember correcty it worked in api level 7 as well though.
Hope this helps...

One possibility is that: when you call setLogText in another Class X. The MainActivity may not be existing anymore, which makes the logger a null reference?

Related

I am using android studio 8.0

I am using android studio 8.0. and I made a simple activity to go to another activity here are these errors are shown
You don't need to call onCreate() explicitely. Once you declare an instance of a class, if it has the onCreate() class, it will be automatically called at the appropiate time.
If you override that class, always be sure to declare the #Override statement above it, this will make sure you're overriding the correct function because if you don't, and you don't specify the correct parameters that the former method has, it will not be called and you'll think it does.
Also, it's a good idea to call super.onCreate(savedInstance) as the first line of your overriden method.
---- EDIT ----
As said above, onCreate() is called on the object creation, i.e., when you declare: alertFunction alertClass = new alertFunction();.
If this is something you want to call several times, put the content in a public function inside your class and call it from onCreate() and from the outside when needed. For instance:
public void myFunction() {
// Put here the current code of onCreate()
...
}
#Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
myFunction();
}
And then if you need to call it again from outside your class, do the following:
alertClass.myFunction();
Source: ERROR: The method onCreate(Bundle) in the type alertFunction is not applicable for the arguments ()
By the way, there is no Android Studio 8.0. Check out this link: https://developer.android.com/studio/releases/index.html
Hope this helps! Good luck!

How to set the values in Textview of MainActivity from simple class

I have two classes One is MainActivity.java and other is simple Java class ConnectMe.java. I have Single Button and Single EditText on MainActivity. I am using a button to Login So it is named also as btnLogin. On its clickListener, I am taking the Ip from the EditText(in string format) and calling the Login function from the ConnectMe.java class which takes string as a parameter.
Now in ConnectMe class I check if the application is connected to the server it should show the Connected Message in EditText and Also it should show the Toast on MainActivity. And I have no Idea How to do this as I am new to android.
here is my sample code
public class MainActivity extends Activity {
Button btngLogin;
EditText etIp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnLogin.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
ConnectMe connectMe = new ConnectMe();
connectme.LogMeIn(etIp.getText().toString);
}
});
}
here is my java class for connection
public class ConnectMe {
MainActivity mainActivity = new MainActivity();
void LogMeIn(String ip){
MyConnectedmethod.Connectednew (new Runnable() {
public void run() {
mainActivity.setText("connected");
}
}
I know the code is not proper, But I just want to give you an idea. I am getting the null point exception on the line in which I am setting text of EditText.
With some research, I have find out that I can not touch the views from the Thread and Runnable directly . and I was told to use runOnUiThread. like mainActivity.runOnUiThread but it is also not helping giving error of nullpointexception.
So Please help me as I am new to android programming
A lot going on here.
There's basically no instance in which you should instantiate an activity.
The Activity doesn't have a .setText() method. So that's the null pointer.
There's a much easier way to do a simple worker task than creating your own thread and managing it yourself. Use AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
EDIT:
You can run as many AsncTasks as you like. Without more context, it's hard to say exactly what your best approach is. But, it sounds like you probably want to run some kind of service. (http://developer.android.com/reference/android/app/Service.html). There's a couple different flavors available, depending on what you want to do. If it needs to run all the time, rather your app is running or not, then use a start service. If it needs to run only so long as the UI is going, then a bound service is the option. If it needs to do something every so often than some combination of intent service/broadcast receiver/alarm manager is the route.
You may not even need a service. If you're just loading several things use the loader manager. For downloading content a SyncAdapter may be the way to go. The point is that after 24APIs most common tasks already have a ready made solution. So, in most cases, you don't need to fiddle with threads yourself.
The NullPointerException happens because you`re missing to declare what object Button btngLogin refers to.
btngLogin = findViewById(R.id.yourbuttonnameinxml);
Do the same with your EditText.
i think you better read this first, starting another activity with intents and sharing a message between two activities (classes): http://developer.android.com/training/basics/firstapp/starting-activity.html

Why does this make my app crash and what's the appropriate solution?

I have a button that I want to change its value often, so my Activity has a private variable :
private Button p1_button = (Button)findViewById(R.id.firstbut);
This simple line makes my app crash. If I put inside the onCreate it works and I can interact with the button (change text etc).
EDIT : I think I found the reason. I should initialize AFTER setcontentview ?
EDIT: Thank you for the constructive answers. I have now a different problem I removed the initialization and I did it on onCreate and it works (But I keeped the p1_button declaration as a private field). But when I tried to modify the button in a different method of my activity (just changing the text), it crashes again. So the return value of findViewById is "local" to the method where it is called and I should setcontentview in every method that access UI elements ?
Do not call findViewById() until after you call setContentView(). Otherwise, the widget will not exist.
More generally, do not call inherited methods on Activity until after super.onCreate(), unless specifically advised to do so.
It depends where you are calling this line.
http://i.stack.imgur.com/6EQaU.png
The onCreate() method contains a call to setContentView() and before this is called, Android has no idea what to do with your button as it hasn't been inflated yet!
Therefore as a really easy rule of thumb, always make sure setContentView (or if you're dealing with fragments onCreateView()) have been called and completed. Only then will findViewById() work.
If you would like further guidance, please post some code in which the crash occurs.
edit: I tried to add the image properly but don't have enough rep.
To understand this you need to know the Activity lifecycle. You are trying to look a view which has not yet been created by Android.
As per the android lifecycle explained here "http://developer.android.com/training/basics/activity-lifecycle/starting.html". In onCreate() method the activity is created and you can access different views of the activity. If you will try to look for view before onCreate() the app will crash as it does not know whether that view exists or not.

Android - Activity onCreate and Fragment onCreate

I'm still new to Android programming, so this question is rather basic. I see lots of code samples on the Internet where UI components, like a TextView, are being initialised and accessed in the onCreate() method of an Activity.
When I use Android Studio to create a new project - FirstApp - with default settings, a blank Activity called MainActivity bringing along with it activity_main and fragment_main, I can immediately compile this into an APK, deploy it on my device, and I get a screen with a header "FirstApp" and a TextView in the top left showing "Hello world!".
If I give the TextView an ID of textview1, and create a member variable, TextView myTextView;, then I can reference it in the onCreate() method of the Activity, like so (no compiler errors, of course):
#Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_main);
myTextView = (TextView) findViewById (R.id.textview1);
myTextView.setText ("Hello tablet!");
if (savedInstanceState == null)
{
getSupportFragmentManager().beginTransaction().add (R.id.container,new PlaceholderFragment()).commit();
}
}
However, if I compile and run the APK it results in an "Unfortunately, FirstApp has stopped." message.
I have previously got around this issue by moving startup code that accesses UI components into the onStart() method of the Activity, like so:
#Override
protected void onStart()
{
super.onStart();
myTextView = (TextView) findViewById (R.id.textview1);
myTextView.setText ("Hello tablet!");
}
Which would result in a working APK with a single TextView in the top left showing "Hello tablet!" - my simple questions are two-fold...
If the project uses Fragments then should I fully expect that the UI components cannot be accessed in the onCreate() method of the Activity, as I see happening with lots of sample code on the Internet, probably because they've not been created yet?
Is it acceptable for me to be accessing UI components within the onStart() method of the Activity (which does work) - or should I be doing something else? Previously I have also used the onCreateView method of the Fragment, but is the best place to access UI components inside a Fragment actually in the onCreate() method of the Fragment, which I have not yet tried?
I also note that the onCreate() method of the default Fragment Android Studio creates for you when you create a new project does not have a stub provided... but onCreateView does, and the lifecycle documentation implies (to me, anyway) that this might be the best place to be doing things like this.
Any guidance on this is appreciated.
The fragment transaction commit command only puts the transaction in Que - the transaction will be processed some time in the future. This is why you couldnt use it straight from on create.
I suggest you to use fragments to encapsulate their Ui behavior - I wouldn't change a fragment's Ui elements explicitly from the activity.
OnCreateView inside a fragment is a good place to init the fragment's Ui elements since it is called when the fragment view is created.
Working with fragments is quite tricky and painful at start but From my experiance they do help to create a much more modular code.
I suggest you read more about fragments in the docs before starting a serious project with them.
http://developer.android.com/guide/components/fragments.html
#chipopo is right in the diagnostics and in the encapsulation recommendations.
But in case you need you can call FarmentManager.executePendingTransactions() after commiting the transaction. This ensures that the operations on fragments queue are execute synchronously.
I used that sometimes in non UI retainedInstance fragments.

Android App - View function

bit of a noob question, I think I'm going about this the wrong way.
This is my first app and I'm trying to set it up into multiple files and classes, my current problem:
For neatness and unforseen use in the future, I had placed my layouts into functions:
public void homepage (){
setContentView(R.layout.layout_homepage);
}
I use the menu for most of my direct navigation and, previously, calling these functions in the
onOptionsItemSelected () worked perfectly.
However, when I moved my page functions to a seperate class:
public class newpage extends MyApp {
//Home
public void homepage (){
setContentView(R.layout.layout_homepage);
}
....
and called them in the function:
public boolean onOptionsItemSelected(MenuItem item) {
//Create new page class
newpage pagecla = new newpage();
...
pagecla.homepage();
....
It crashes the app, and when debugging the only sense I can make of it is a NullPointerException.
I'm guessing I have to give it some kind of value for View, but I'm really not sure what.
Don't do this. Each activity should have a call to the setContentView() function to intialise the function. Shouldn't need to externally reference it.
You should invoke setContentView from your activity, not your Application. If you want to do this from your Application anyway (don't know why), you should provide a reference to your activity. But it's an awful design, plus you shan't name your class pagecla, you'd better read about java naming conventions.
It seems that you lack OOP knowledge also. Your function is in fact a method, which needs an object to be invoked on. It's your Activity before your refactoring and your pagecla after it.

Categories

Resources