android cross activity interfaces - android

Say I have two active activities, A (has a window) and B (has a view embedded in A, but is still it's own activity).
The activities are in different packages but running in the same process.
A view in activity B is added to a view in A that implements an interface I. The declaration of I is in a library shared between A and B.
So I would assume that I could do something along the lines of this inside of an instance of B:
viewInA = viewInB.getParent();
(I)viewInA;
But I get a casting error. Is there a way to make this work?
Doing a bit of introspection can easily prove that viewInA does in fact implement I. The package that I resides in is, of course, the same for both activities.
My set of restrictions due to the situation is rather unique; Doing simple message passing with intents won't work.
I could create a wrapper that uses introspection to get the Methods on the view that I know exist. But that's ugly and I'm lazy.

Everything else aside, if you get a casting error in Java, it's because viewInA does in fact not implement I. Be aware that getParent() returns a class implementing ViewParent... (i.e. does I extend ViewParent??)
Nonetheless, you can set a breakpoint, and check at runtime what type viewInA has!

Related

Fragments have "getActivity()". What do additional Activities have that mimics this behavior?

In Android development using Java, Fragments have "getActivity()" that will give you the reference to your MainActivity. I am wondering if there is a method that gets the same exact type of reference of MainActivity but from a different Activity, rather than a Fragment.
IE: (Not in code, more of a diagram)
MainActivity - "this" : MainActivity reference
Fragments - "getActivity()" : MainActivity reference
Activity 2 - "this" : Activity 2 reference
Activity 2 - ???? : MainActivity reference
Activity 3 - "this" : Activity 3 reference
Activity 3 - ???? : MainActivity reference
In this example, I am attempting to visually show you what I am looking for. Essentially, fill in the "????" (Hopefully it makes sense)
I have tried many things and researched plenty. There are plenty of posts describing a few right ways to pass data between activities and many more wrong ways, but this is not about passing data between activities. It is about having a reference to the MainActivity from within other activities.
Is having access to MainActivity from other activities possible? Or is it just bad practice? It seems like it should be as easy as getActivity() is from a Fragment, but maybe I am missing the concept.
Things I have tried that have not worked are.
1. Passing the MainActivity reference itself through an Intent, this fails because Activities are not Parceable. (I can pass parceable data and other variables just fine, but not an Activity)
2. I have tried making the activity a child of MainActivity in the AndroidManifest and as well as adding meta data claiming it is the child. This is help get a non_null return from get getParentActivityIntent(); However, it does not provide any way to get that MainActivity reference from that.
3. I have tried getParent(); This always returns null.
4. I have tried getCallingActivity(); This always returns null.
5. I have tried getApplicationContext(); This doesn't seem to have a way to funnel down to a MainActivity reference.
6. Definitely many more things that aren't worth mentioning or forgotten.
I am essentially road blocked for 2 days now researching this, until I can figure out a way to get this reference. There are many posts you would think are relevant, but do not actually pass the true reference, or answer my question directly or even indirectly. The thing that always road blocks me in Android Java is not being able to reference something I need to get a reference to. Every. Single. Time. Everything else usually flows pretty smooth when you can access the things you need access. :)
Thank you for your help and time.
That's not how activities work, no. Each activity is totally independent of every other activity and there's no way for you to safely access any other activity. That's why abstractions that live within a single activity like fragments are useful and why the Single Activity pattern is recommended.

How to make KotlinX access parent activity's synthetic properties directly?

I'm using this library in my app. The way I've written is that I have a MainActivity with the layout as provided by the library viz. something like this:
<SlidingPanel>
<MainContentLayout>
<SlidingPanelContentLayout>
</SlidingPanel>
The MainContentLayout is basically a FrameLayout where I load a fragment into. Now here's where it gets tricky--the fragment has code that accesses the slidingupPanel's layout components. When I type the component in Android Studio it automatically imports the correct synthetic property class file as import kotlinx.android.synthetic.main.layout_sliding_panel.* and even autocomplete works to show the correct fields as properties. However, when I run the app is crashes saying that field is a null. To fix this, I have to add (activity as MainActivity). as a prefix to all the fields. And when I run this, it fixes the issue.
Is there a cleaner way to do this because writing (activity as MainActivity). in so many locations seems annoying. Is there like a kotlin directive for this and why doesn't KotlinX view binding library auto-detect that the sliding panel layout is on a different layout and therefore write to correct convenience class to access this properly without crashing the app?
I understood your question like this: you are trying to access one of activity's views from fragment it hosts.
Such approach is not good as it couples activity and fragment (thus making fragment non reusable in other activities). If really needed, interaction between activity and fragment can be done using interface activity implements. However you need to keep in mind fragment's lifecycle (in other words activity reference is not always accessible inside fragment). Last but not least, nothing wrong with kotlin extensions.

Best way to access a parent Activity's data

This is a stylistic question more than an actual "how can this be done," but the basic situation is this: I have an Activity MyActivity which contains a MapFragment, as well as a List of Renderers which are my own class that takes care of displaying some data. The Renderers also have ViewPagers which get their content views from yet another class, let's call it ViewPagerTab. Sometimes, something happens in some of these ViewPagerTabs that necessitates the update of the map in the top level Activity. There are, as I see it, a few approaches:
1) Both my Renderers and my ViewPagerTabs contain a reference to the context. If I cast the context as MyActivity I can access its map parameter.
2) By using the reference to the context, I can call getSupportFragmentManager().findFragmentById(R.id.map)).getMap() on it and get the map that way.
3) I can pass the map down from the Activity to the Renderers to the ViewPagerTabs as they are created so the map is accessible in each as a class variable.
4) Use a BroadcastReceiver in my Activity and send a message to it when the map needs updating from my ViewPagerTab.
Have I missed anything? What's the best/cleanest way of doing this?
This lesson may give you some ideas:
Communicating with other Fragments
Basically, the idea is to define an interface in a subunit such as a Fragment, then implement it in the parent Activity. Then, actually call the methods in the interface in the Fragment.
Another alternative is to create a class that extends Application. There, you can "share and declare" a number of non-context specific variables (like a glorified container, but where you don't have to create multiple instances of, or do look ups).
Requires some setup in your manifest but then all your activities can call MyApp app = (MyApp) this.getApplication(); (or in fragments, via the onAttach activity's .getApplication() )
The standard way is to define a listener interface, but I've found this to be cumbersome. Otto is a really nice alternative that you should at least look into before making your decision.
I think this is a bit over my head but what about parcel.I think it wouldn't work because of the dynamic nature of your data however it is one way to communicate between activities.

How to not write spaghetti-code/huge activities w/Android?

I'm trying to avoid having gigantic activity classes that are hard to follow, but the platform seems to be making it hard. Doing almost anything requires a activity or context - these can be stored away in a helper class, but unfortunately calls like startActivityForResult, for example, don't take a sperate listener but always call back on the same activity on an override with a supplied integer code - so this means that seperation of concerns is hard - the main activity needs to know about the helper class and dispactch to the helper class based on an request code - and of course, that request code needs to be unique, so that's a leaky abstraction as well. Why not specify a listener for every call thus avoiding the dispatching and need for unique request codes? Any other ways to slice this?
thanks
In API level 11 and higher, you can use Fragments.
Specifying a listener would be difficult since it would require passing an object to other processes in the Android environment- remember that activities can be called from one application to another.
How is using request codes making your activities "huge" in a way that listeners wouldn't? Activities should make use of classes defined elsewhere to do more most of the labor, let your activities pertain primarily to UI tasks.

What exactly does using the Application Context mean?

I'm new to this and I'm sorry if this is a really dumb question. I'm just trying to clarify things. My book says I can retrieve application context for process by using the getApplicationContext() method. I just really don't know where to type this or what to do with any of it. I can go to the hierarchy but what do I do with all the script there. Also where would I write Activity Callbacks, in the main.xml? An exercise wants me to add a logging tag to my project but I'm not sure how to do this. The exact text says:
"Within the onCreate() callback method, add an informational logging message, using the Log.i() method."
and another exercise says to:
"Implement some of the Activity callback methods in addition to onCreate(), such as onStart(). Add a log message to each callback method and then run the application normally".
As these seem like basic questions, can someone please help me.
I am using the Android SDK, and Eclipse. I have made the Hello World application, but I have no idea what to do with Context or Retrieving resources. Please help!
The first rule I would give you: if you don't know why you need it, you probably don't need it. Use your activity object as the Context when you need a context.
The callbacks you talk about are on the Activity class. The Application Fundamentals describes what an Activity is: http://developer.android.com/guide/topics/fundamentals.html#Components
The only time you want to use getApplicationContext() is when you need a Context that exists outside of the lifecycle of an Activity class (or other component). You'll want to find documentation on specific cases where this is desired, there is a lot floating around. For example this one is part of the Android documentation: http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html
For the tasks you're working with here, you'll be using the Java code that defines the behavior of the application, not the XML files that define resources and layouts or the AndroidManifest.xml file that declares basic application properties.
If you're working with Hour 3 of the Sam's Teach Yourself... book, then you need to open the src\com.androidbook.droid1\DroidActivity.java file. In general, you would need src\<package-name>\<class-name>.java. When you open that file, you'll see a class (in this case, DroidActivity) that extends Activity and already has the onCreate() callback method. Anything that you want to happen during onCreate() goes inside that method. Other callback methods can be added inside the activity class. To see an example that has all the lifecycle callbacks (but doesn't do anything in them), look here.
A logging tag is just a string. You can declare it, for example, as a private static final String inside the activity class.
If there's confusion about where methods belong, where and how to define variables or constants, how to call methods, how to use classes, and so forth, then it might be best to go through an introductory Java text before starting with Android. There are plenty of free resources available for that.

Categories

Resources