Android: Visual A/B Testing library - android

I am developing a small A/B Testing library for Android. Library will only be initialised in application class. I need to change TextView values.
I will store all the data fetched from the in a file. But I am not able to track when ever a TextView gets into view and moves it.
For example TextView A is in X Activity, TextView B is in Y Activity and TextView C is in Z Activity. Since the variable I have is Context, how should I change TextView A, B, C values.
I need to figure out which Activity is Visible. From the Activity I will be able to get root view. And I will iterate over child views and change value. But How should i listen to Activity Change.
Is there any other approach to this ?
I know this is possible as many A/B testing library are doing this.

Here you go, check out my answer over Here
As you've mentioned, hooking into the activity lifecycle callbacks via AppContext is the best way to start. From there, you'll have all of the information you could possibly need. Every time the activity switches, you'll have the Activity object, and from there you can get the root view and apply changes as necessary.
I would advise against an iteration over the views though! If you have the rootview, you can just do a findViewId(textview C id) on that root view and you'll grab your view!

Since you are building a library, you can expose a function which can be called after onCreate of each activity, which will give you reference of the activity. Once you have the activity, you can get it's root view and do whatever magic you want to do.
That's the only other approach if you don't want to register LifeCycle callbacks for activity. The application needs to enter your library at least at some point of time. Either you can make the application do manually ( above approach ) or you can override all life cycle events of all activities ( registering lifecycle call back ).

Related

Why can't fragment save EditText state by default on orientation change?

I have a fragment, which contains many EditTexts.
And when I rotate the device the EditText goes blank. The fragment is not saving its state/value. But at the same time if I use that fragment layout for activity it stores the EditText's state.
And yes I've given the IDs to each EditText, even to each view if that matters.
I know I can use saveInstanceState to save those values but is there any other way to do it? Cause there are almost 20 EdiText in that fragment, so should I use saveInstanceState, will it be okay to save these many variables/values in saveInstanceState?
Update:
I was recreating the fragment in activity on orientation change, so that was the reason, EditText was unable to save its state.
Such a silly mistake!
So now I just used saveInstanceState like following:
if (savedInstanceState == null) {
initialiseNewTaskFragment();
}
And that's it. EditText is saving its state now.
Thank you JorgeGil for saving my time!
Well this is a fairly loaded question lol.
So let's start with a few points.
First, you can of course handle your own lifecycle change if you choose to NOT allow Android to reset your lifecycle on device rotate.
android:configChanges="orientation"
Use that flag in your manifest if you want to retain everything and handle your own rotation changes. However, if you have a layout-land folder with different XML files, you will not want to do this.
Yes of course you can do fragment.retainInstance when nested in Activities to get it to retain values. However, retaining populated Elements with values is not something you can just natively expect it to do as the UI elements were completely redrawn, so something has to tell it to redraw it again.
So if you are going old school and you are actually still doing findViewById and myText.setText('some Stuff'). Then you may find some time savings in using a library like icepick.
https://github.com/frankiesardo/icepick
However, the BEST option by a mile is to modernize your coding practice to use DataBinding. This allows you to not care about the UI interactions anymore as the values are bound to your Fragment or Activity or Model values by default and can be done with 2-way binding. This ensures databinding always populates with the value that was last updated.
Imagine you have an object of
public class Student implements BaseObservable{
String firstName;
}
Then in your xml you have
editText
android:text="#={student.firstName}"
Obviously there is a little more, like you need to set your student object in the onCreate to ensure it is in the XML for using. But when the user modifies the student firstname it is retained in the model, and redrawn automatically into the Edit Text.
This is your best solution, but depends on how invested you are in the future binding techniques of Android development or if you just prefer to go status quo to get across a finish line.
Hope that helps.
Add this in your Activity tag on your AndroidManifest.xml to avoid the recreation of the Activity and you won't lose the data.
android:configChanges="orientation|screenSize"

How to use finishActivityFromChild() and finishFromChild() in android to have more control on activity lifecycle

I am just trying to end the Activity that was started before two or more activities, like based on a condition from 'N' th Child, not the immediate child activity,i want to remove activity from stack,
I dont want to pass on information through all the child classes and get result by startActivityForResult(),
so will I be able to use finishActivityFromChild() or finishFromChild() to achieve this ?
If not at least explain me why are these method used in android with good example since i don't see many people using this function anywhere.

Call function in parent Activity from child Activity - Android

How can I call function (with parameters) in parent activity from child activity in Android. I iOS is simple with delegate and protocols, but in Android I found that can be a problem if the screen is rotated.
I also do not want to use startActivityForResult because I do not want to close the child Activity.
ADDED:
I am creating a library so other developers can attach it to their project. In developers activity they put button that shows my(by my I mean from library) Activity and when something is done in my activity I instantly need to inform the main project(activity) that something happened (via function or something), but I do not want to close my activity yet. I also should not change their code a lot and it should be easy to include to their code.
The point is that once you started a child activity, Android might decide to close your parent activity at any time, if system requires more memory. This means you cannot rely on the fact your parent activity still runs. That is why you cannot use static variable approach either, because parent activity might not be there already.
If you want your app to run reliable in any situation you have to use startActivityForResult and close child activity.
If this is not acceptable for you because of some reasons, you might share more details and we will try to find an appropriate solution for you in terms of Android concepts.
ADDED: I am creating a library...
As already mentioned, you cannot control whether your parent activity gets closed or not as long you started a new child activity. Android can kill your parent activity at any time and you need to be prepared to handle this situation properly.
To solve your problem you need a place, which is shared between parent and child activities. A sequence will be like this. Parent activity starts a child activity and goes into background. User changes something in child activity and it stores changes (as data) into the shared place. At this step it doesn't matter whether parent activity still running or now. Once parent activity is visible again, if must read data stored by child activity, and update itself accordingly. You can use onStart() method for this.
Now about that shared place. I would discourage you from using a static variables. Instead you could use Application object (it's a singleton) or shared preferences (they are also shared).

Change another activity without open it

Is it possible to add a textView on Activity B without showing it?
What I mean is, when i press a button (on DiallerActivity), then a textView will be added on HistoryActivity without leaving DiallerActivity.
How can I do this?
is it possible to a add textView on Activity B without show it ?
No, not directly.
An Activity is a special case Android class and shouldn't be treated as a normal Java class. Effectively the purpose of an Activity is to act as a framework for a UI so, if an Activity isn't visible then there basically is no UI. In other words, how can something be a user-interface if the user isn't able to see or interact with it?
As logical Chimp suggests, the changes should be with respect to some form of data history (a database or SharedPreferences) and it is the responsibility of your HistoryActivity to update its visual elements (TextViews) next time it is started.
One Activity shouldn't try to modify the look, feel or behaviour of another Activity except indirectly by changing some form of global data or state or by passing data to it if the first Activity is responsible for starting the second.
hmmm - not sure I fully understand your question. Are you wanting to append the dialled number to the 'HistoryActivity' without showing it?
If so, I suggest you separate your data (list of dialled numbers) from the view (HistoryActivity). Then, you only have to add the dialled number to the data record used to hold them (suggest a list). When the user opens the HistoryActivity, then you can just draw as many text fields as required to display the data.

includeed layouts - update in multiple activities

I have an app with multiple activities and multiple layouts. However, one piece of layout is included on several activities. I also have a thread which updates this layout. However, when i switch activity it doesn't work. Since the layout is included the elements have the same ID's, shouldn't it just work? Or do I really need to fetch an object for each element in the layout and feed it into my thread in order to make it update the elements in a new activity?
You should run the update code for each Activity/View, although the XML included is the same, each is a different instance.
My suggestion is on Restart verify is there is any modification to do in each activity, a simple way is to each Activity extend a BaseActivity that has this code.
I include a layout for adverts in my app, but on each activity that uses it, the adverts need to be reloaded.
If I call an activity from one that is using the same included layout when I go back to the previous activity it's still there.
I guess this is what you are seeing....
So you can also save that data inside sharedPreferences (if it is little data and primitive objets or parceable objects).
Also you can extend the Application class and store the data there and update every activity inside the onResume() method. that i believe is the best way to handle this. and this is quite simple to do.
Ask google about extending the application class and he will provide tons of results on how to do it. its an easy way to pass data between activities and/or keep a reference to a single object which you will use throughout the app. Just be carefull to clear it when you wont need it anymore because it will stay in existance untill the application is finished() (which comes with the application extension living thru the whole application lifetime).

Categories

Resources