Android passing variables between activities - android

I want to pass one or more variables between activities in android. One solution is to use global variables, and it is explained here:
Android global variable
which I repeat here:
You can extend the base android.app.Application class and add member variables like so:
public class MyApplication extends Application {
private String someVariable;
public String getSomeVariable() {
return someVariable;
}
public void setSomeVariable(String someVariable) {
this.someVariable = someVariable;
}
}
Then in your activities you can get and set the variable like so:
// set
((MyApplication) this.getApplication()).setSomeVariable("foo");
// get
String s = ((MyApplication) this.getApplication()).getSomeVariable();
I want to use this and set a global variable in one of my activities when an item on a ListView is pressed. So I have this code:
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
.
.
.
((MyApplication) this.getApplication()).setSomeVariable("foo");
}
});
However I get an error which says "The method getApplication() is undefined for the type new AdapterView.OnItemClickListener(){}".
I would like to know what is the reason I get this error and how to fix it, or a better way of passing a variable from one activity to the other.
Thanks,
TJ

Inside an Anonymous Class you cant say this. u have to specifi the Class around the inner class.
like MyApplication.this.get..
when using:
class MyApplication {
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
((MyApplication) MyApplication.this.getApplication()).setSomeVariable("foo");
}
}
}
the "this." inside an annoymous inner class refering to the inner class itself.

Any particular reason you are not using Intent's? http://developer.android.com/guide/topics/fundamentals/activities.html#StartingAnActivity

You have the use MyClass.this.getApplication() if you've define the anonymous OnItemClickListener in a member function of MyClass. OnItemClickListener does not know about the application.

I don't think you need to cast it... Application is already there.
MyApplication.getSomeVariable();
should work just like any other class.

Related

Android: Access view objects outside of the activity

Please correct me if my OOP application is incorrect. I have a custom Android class at /src/myworkspace/MyObject.java that does not extend anything.
public class MyObject {
...
public void methodOne() {
...
}
}
Within the main activity, MyObject.methodOne() is called.
How would I manipulate view objects in methodOne?
For example somthing similar to
mButton = (Button) findViewById(R.id.button_one);
mButton.setOnClickListener(mButtonListener);
The methods of MyObject are reused in many activities. If this approach is incorrect, where should the repeatable code be stored?
I would suggest MyObject receive a view as a parameter:
public class MyObject {
...
public void methodOne(Button button) {
...
}
}
The just call it this way from your activity:
... activity code ....
MyObject obj = new MyObject();
Button button = (Button) findViewById(R.id.button_one);
obj.methodOne(button);
.... more activity code.
You can use other approaches too :
Bind MyObject to activity in the constructor :
MyObject(Activity owner) {
.. assign activity to member
}
Use Object as a nested inner class.
Activity
class MyObject {
Each has it's merits or gotchyas, I personally would stick with passing a view by parameter, it is the most loosly coupled, and IMO the simplest and least error prone.

If OnItemClickListener is an interface in Android, how can we create an object based on it?

I am using the following code from this site:
// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
// Do something in response to the click
}
};
listView.setOnItemClickListener(mMessageClickedHandler);
Now it says that:
You can respond to click events on each item in an AdapterView by implementing the AdapterView.OnItemClickListener interface.
If OnItemClickListener() is an interface then how can we create its object as in above code? What is the concept behind that?
I'm not quite sure I get your question, but in your example above mMessageClickedHandler is the object, and the object implements the OnItemClickListener.onItemClick method. If you are coming from a C++ world, there you would need to implement an OnClickListener subclass or the like as a separate entity, but in Java you can, as seen above, create an anonymous subclass (I hope that's the correct designation!) in inline code.
It's not a technique I personally like that much, but it's such a common Java idiom that I just go with the flow!
You can't create an object for a interface. Anonymous inner classes allow you to do the following, though:
public interface MyInterface {
public void myMethod() ;
}
MyInterface myIntfObj = new MyInterface() {
public void myMethod() {
}
};
myIntfObj.myMethod();

Calling findViewById() from outside an activity

Is there any way to access a layout's view from a non-Activity-derived class? I'm creating an Accordion class and need to access some of the activity's UI elements. I'm passing in the activity's context to my accordion class's constructor, but the findViewById API is only available from the Activity class. I also don't want to pass in an instance of my activity since that seems to be frowned upon due to potential memory leaks.
I'm pretty sure you can just pass an activity as a parameter, e.g.
public void initSouthViews(Activity activity) {
for (int i = 0; i < southScores_.length; ++i) {
southScores_[i] = (EditText) activity.findViewById(10);
}
}
Here is something that might be helpful.
public interface IViewRequest {
public View requestViewByID(int id);
}
public class MyActivity extends Activity {
private IViewRequest viewRequest = new IViewRequest(){
public View requestViewByID(int id){
return findViewById(id);
});
}
public class Accordion(){
private IViewRequest viewRequest;
public Accordion(IViewRequest viewRequest){
this.viewRequest = viewRequest;
}
private View findViewById(int id){
return viewRequest.requestViewByID(id);
}
}
I have never tried something like this. I also don't know if it won't cuase any memory leaks. But it does what you asked :) "Calling findViewById() from outside an activity"
Activity's context is in fact the Activity class itself. Assuming that this object will live inside only one Activity, it should be safe to pass object of type Activity to it. Otherwise, think about reengineering your Accordion class.
I passed in an instance of one of the Views into the class's constructor.

Having difficulty with a global variable in android application

Hey I am having trouble declaring, changing, and using a global variable. I tried the whole "make a class that extends your application and put variables there" thing but I'm not sure how to implement it. Here is my class with the variable in it.
public class MyApp extends Application {
public int listPos;
}
I then tried to access and change int listPos here.
public class Browse extends ListActivity{
MyApp app = ((MyApp)getApplicationContext());
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] coffeeTypes = getResources().getStringArray(R.array.coffeeTypes);
setListAdapter(new ArrayAdapter<String>(this, R.layout.listview, coffeeTypes));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
app.listPos = position;
startActivity(new Intent(Browse.this, CoffeeTypes.class));
}
});
}
}
Then I tried to access the variable in the following activity to determine the outcome of an if else statement
public class CoffeeTypes extends Activity{
MyApp app = ((MyApp)getApplicationContext());
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(app.listPos == 0){
Toast.makeText(this, "WEEEEEEE!0", Toast.LENGTH_LONG).show();
}
else if(app.listPos == 1){
Toast.makeText(this, "RAWR!1", Toast.LENGTH_LONG).show();
Anyone have any idea what I am doing wrong?
You can use soorya's answer with some modifications. I would personally still use your myApp class but change listPos to static and access it that way. Doing it this way lets you use the Application class onCreate method to initialize values if needed (though it won't be needed in this example) or other Android methods.
public class MyApp extends Application {
public static int listPos;
}
//~~ Elsewhere:
MyApp.listPos = 5; //etc
But this isn't the best way to handle your type of problem.
You should be passing the list position information (or the id of the item clicked or however you are handling your data) via the Intent.
Instead of having a global variable to track this information, keep it local to just the Intent:
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//app.listPos = position;
Intent intent = new Intent(Browse.this, CoffeeTypes.class);
intent.putExtra("position", position);
startActivity(intent);
//startActivity(new Intent(Browse.this, CoffeeTypes.class));
}
This passes the position data to the new Activity via the intent. In your CoffeeTypes Activity you should start with something along the following:
//in onCreate...
int incomingPosition = getIntent().getIntExtra("position",-1));
if(incomingPosition != -1) { //do stuff }
This will read the "position" data from the incoming Intent so you can use it. The -1 above is the default value if nothing is added.
One final warning: you might want to be careful sending the list position back and forth, depending on how your application is set up if new items are added/items are deleted the list position might no longer refer to the item you thought it did. If these coffee types/whatever you are using have a separate unique ID that might be more appropriate to avoiding the above situation, consider using that instead.
I'm not sure if it's a visibility issue with the android OS, are you able to make an public functions that may be able to act as getters for the variable?
int getListPos(){ return this.listpos; }
I know that you can pass variables between contexts, you may have to do that.
Perhaps a temporary workaround to get you moving could be creating a static class of accessible variables too?
Create a class like this
class globalClass
{
static int lastPos;
}
You can set values using
globalClass.lastPos = value;
and get function is
int myVal = globalClass.lastPos;
i do Application variable classes by making the variables private, and then create public get() and set() methods to change the variables. you can try that, but it seems like you are doing it right, technically
one reason why it might be going wrong is because you are implementing the stuff in onCreate and not onStartCommand. if you are testing this function with the wrong assumptions/knowledge of the Activity cycle, it could go wrong

How can I call a function in my main Activity class from a custom Gallery view in Android?

I have a custom gallery view in which I am overriding some methods. I would like to be able to call a function in my main activity from this class. How do I make a reference back to my main class?
I thought I'd just push the class reference into CustomGallery by creating a setter function ---> g.setBaseClass(this);
CustomGallery g = (CustomGallery) findViewById(R.id.playSelectionGallery);
g.setSpacing(10);
g.setCallbackDuringFling(false);
g.setAdapter(new ImageAdapter(this));
g.setSelection(1);
registerForContextMenu(g);
g.setBaseClass(this);
Problem is this is of type Context and someFunctionToCall() will result in a not a member of this class error. In my custom class I have:
public void setBaseClass(Context baseClass)
{
_baseClass = baseClass;
}
private void callSomeFuntionOnMyMainActivityClass()
{
_baseClass.someFunctionToCall();
}
All I want to do is call back to my main class, called ViewFlipperDemo. This would be easy in As3. Any thoughts? Hopefully I'm missing something really simple.
That's actually not a good idea... but you can do it this way:
private void callSomeFuntionOnMyMainActivityClass()
{
((ViewFlipperDemo)_baseClass).someFunctionToCall();
}
What you should do instead is implementing a simple observer which allows you to notify the Activity that something happened. That's one of the main OO principles, your custom class shouldn't know anything about your activity class.
Observer pattern example
The Observer interface:
// TheObserver.java
public interface TheObserver{
void callback();
}
Your custom view:
public class CustomGallery{
private TheObserver mObserver;
// the rest of your class
// this is to set the observer
public void setObserver(TheObserver observer){
mObserver = observer;
}
// here be the magic
private void callSomeFuntionOnMyMainActivityClass(){
if( mObserver != null ){
mObserver.callback();
}
}
// actually, callSomeFuntionOnMyMainActivityClass
// is not a good name... but it will work for the example
}
This is the activity that will benefit of the observer (notice that now you can use your custom view on different activities not just one, that's one of the key reasons to implement it this way):
public class YourActivity extends Activity{
// your normal stuff bla blah
public void someMethod(){
CustomGallery g=(CustomGallery)findViewById(R.id.playSelectionGallery);
g.setObserver(new TheObserver(){
public void callback(){
// here you call something inside your activity, for instance
methodOnYourActivity();
}
});
}
}
You will notice that this design pattern (observer) is widely used in Java and Android... almost any kind of UI event is implemented using observers (OnClickListener, OnKeyListener, etc.). By the way, I didn't test the code, but it should work.

Categories

Resources