I have a fragment which contains a RecyclerView and sets it up with an Adapter separated in an own class.
In the fragment class I have a private boolean member which indicates whether the application is in "two pane" mode or not. This member gets updated in the onActivityCreated method.
I gotta use this variable in the adapter.
Previously the classes were nested, so I could directly access it. Now it is in another scope.
I have two ideas:
1. Simply make the member public and static (seems a little bit unprofessional because I donĀ“t want it to be changed from outside)
2. Use an own NotifyDataChanged class to which both the fragment and adapter can subscribe.
What is the best practice doing this in android?
Can't you place the boolean flag in the Activity and pass context in the Adapter's constructor, then check the flag's state through context in where you need to use it?
Related
While I was coding, I wanted to use findViewById method to find a view that cant access in the current view but can be accessed via the MainActivity. So two options came to my mind. One is creating a static method from that object in the MainActivity class and access the static object. The second method is to create a static object form MainActivity class itself(this) and access the findViewById method by calling the static object. Please answer the method I should use.
And apart from that, it got me thinking that whether an Android developer should come across this type of scenario or whether I have done some improper coding to access findViewById method in MainActivity while I was in a different view.
You can take a look at the code in the below repo.
https://github.com/chrish2015/ExpenseTrackerLatest
Thanks
If you are inside a class that is neither a Context nor an Activity and you need to use a method which exists inside the activity or context, then simply pass the activity as a parameter to that class and take an instance to that activity inside your class.
public class MyAdapter extends ArrayAdapter { // this is not activity
private Activity mActivity; // activity is a member of this class.
public MyAdapter(Activity activity, List<String> data) {
mActivity = activity;
}
public View getView(...) {
// if you need to use findViewById:
View view = mActivity.findViewById(R.id.some_id);
}
}
Don't use any of your two methods.
I might be misunderstanding your first sentence, but just to be sure, are you asking for a way to access a View that exists in the MainActivity, while you're inside of a Fragment?
If that's what you're asking, then yes, as an Android Developer, there will definitely be moments where we come across this scenario. However, the solution is definitely NOT by making your Views or Context static.
This is one of the easiest ways to cause bugs to appear throughout your app, with a very high chance to cause memory leaks too. Here's an Article from Google talking about memory leaks related to keeping a reference to a Context: https://android-developers.googleblog.com/2009/01/avoiding-memory-leaks.html
Rather than your two options, there are better solutions that developers typically use.
First of all, keep in mind that you should NOT be directly accessing any Views from outside of your current layout... meaning, that if you're in a second Activity, you don't directly access Views from the first Activity, or if you're in a Fragment, you don't directly access Views that belong to it's FragmentActivity.
Instead, you let the Activity or Fragment handle it's own Views.
So for example, if you're in another Activity and you want to update some data in the previous Activity, you can take advantage of an Activity's startActivityForResult() and onActivityResult() to obtain the data necessary to update the Activity immediately upon returning to the app.
For Fragments, there's actually a tutorial from the Android Documentation that describes a very good way to communicate between other Fragments: https://developer.android.com/training/basics/fragments/communicating
This method is to use interfaces as a callbacks, so another Fragment or the Activity will be able to receive data and update it's Views within it's own layout.
So for your case, if you're using Fragments and an Activity, you can easily have your fragments and activities communicate to each other in a safer and more reliable way.
Also, make sure you read up more on static and it's effects on your code, especially the side effects on Android components. Do not carelessly use static without considering some of the effects it might cause, because that would cause an endless amount of trouble to your code.
In my fragment I have a 'dismiss' button that should behave in a different way dependent on which Activity called its parent activity (say TutorialActivity).
In the TutorialActivity I am already determining which Activity called it. How to pass that data down to the fragment?
My fragments reside in a PagerAdapter and I wouldn't like to need to pass this info as a 'newInstance()' parameter every time, as it seems an overkill, taking into consideration that this parameter would be the same for each fragment in my FragmentStatePagerAdapter.
You can access the variable from Tutorial Activity by making this variable public. Suppose variable name is parent. You can access it by using instance of TutorailActivity (suppose instance of Activity used in fragment is mTutorialActivity) then it should be like mTutorialActivity.parent.
But you need to pass instance of TutorialActivity as it may be used for other purposes also like fetching strings from strings.xml and other purpose. So it would be beneficial to pass Activity instance instead of variable.
What I ended up doing: I implemented said "different behavior" in the TutorialActivity itself, having moved the dismiss button up from the fragment. Then a simple onClickListener and a switch statement inside of it.
I have an activity that consists mainly of a viewpager. The user can open new versions of that activity with different intents, thus making the data in the viewpagers different. Problem is when I access static variables in other classes from the main activity type, it seems as if it is editing variable values in all open versions of the activity. If I finish() the top activity,the data in the original activity has changed to that of the child activity. What is a way to keep references to static variables with only the current activity?
Thanks!
What is a way to keep references to static variables with only the current activity?
Quite simply - you can't.
In Java when you declare a variable as static in the main body of the class, it is a 'class variable'. This means that all instances of that class share only one variable between them. Consequentially (as you've already found out) changing the value in any instance of the class will change the value for all instances as there is only one 'copy' of the variable.
A golden rule in Android is to NEVER use static variables or methods in Activities.
There are two reasons for this - if your Activity is only ever extended within your ouwn code, then having a static variable or method is pointless and (as you've discovered), it's counter-productive.
The second reason is that static is often used with the public modifier in order to allow an 'all-areas' access to variables and/or methods regardless of whether an actual instance of any given class exists or not - in the case of the class being an Activity, this is a VERY dangerous game to play because of the life-cycle of Activities.
If you have a 'base' Activity which you want to start various instances of but want a common variable they all need to have access to, then simply declare it as...
protected Object myVariable;
...replacing Object with whatever type of variable you want.
Each Activity will get there own instance of myVariable and can change its value without affecting any other instance of the same Activity class.
See the following for Java Class Variables
In my last project in the activities I had a lot of MyActivity.this provided to the methods requiring context, so I decided to make it like this in the beginning of the class
private Context context = ActivityStage2.this;
and then just pass context to object methods. So far it works ok, but is it ok at all to declare the Context like that? I mean does that always have the updated state of the MyActivity.this each time the context object is referenced?
You can do it but there is no point in doing it.
You basically "cache" the this reference to a field. The field initialization will run just before the constructor body, so every time the object is recreated the reference context will be updated. This works similarly to this, which points at this instance object.
Now why would you do that? Readability? It seems like you want to use it in inner classes, because you explicitly qualify it with: ActivityStage2.this. The java way to qualify the outer class reference from an inner class is well understood by programmers, and here the gain is little. One exception could be anonymous inner classes where you don't have the name of the inner class. In this case caching the reference to the Activity makes sense, but I'd rather use a final local variable instead of a field.
Another reason for doing this could be that you need only the Context interface instead of the ActivityStage2 interface: that makes sense theoretically but in practice I wouldn't do it without some other better reason.
Last thing: if you turn your field in a static one, you will indeed leak.
There is no problem to do this if you follow the two rules listed bellow:
Keep the reference in a instance member. If you use a static field, your Activity instance could never be recycled by the GC because your MainActivity class has a strong reference to the object. If you really need to do this, use a WeakReference.
Keep a reference to your Activity instance. Do not keep a reference to other activity due to the reasons I have just described above.
Otherwise it all depends on you and your code style :)
In my Android project I have an Activity and a Widget (Broadcast Receiver). Both have a simple button. When either of the buttons is clicked, the same action should be executed:
First of all, a Boolean variable should be set to it's opposite value (true to false, false to true). This Boolean should be stored independently from both the Activity's and the Receiver's life cycles.
Then, depending on the Boolean's old state, one of two methods should be executed to query a SQLite Database.
I need something like a Singleton Activity, which has its own Shared Preferences and methods and can be called from various Activities / Receivers.
What would be the best way to implement something like this?
Doesn't sound like anything you want to do requires an activity. I would just write a POJO singleton with a private constructor and a static getInstance() method that returns a reference to a private static instance of the class itself, after initializing it if needed.
Then you can have an instance method that toggles the variable and fires off an AsycTask or whatever to do your query. The state of the boolean can be stored in a private instance variable, or persisted to SharedPreferences depending on how long it needs to be retained.