In class A a have a method that updates a view.
First I called Class b to download some data, once the data is recieved I call the method in class A.
When the view is updated (when the method is called from class b) the view is throws NPE.
However if the view is updated (when called from its native class (class A)) it works perfectly.
Class A is an activity.
In some cases it reported there is some sort of context problem.
I have tried implementing an interface however even that threw an NPE
How can I fix this problem?
public class A extends activity {
public() {
}
B b = new B();
b.doSomething();
public void myMethod(String string) {
textView.setText(string)
}
}
public class B {
public void doSomething() {
String data = getData;
A a = new A();
a.myMethod(data)
}
}
You should not call new A(). This will not invoke a new Activity with the application lifecycle, and will not provide you a reference to the original Activity that contains the View you are trying to update.
I would recommend A should implement a simple interface YourInterface that contains a void callbackMethod(String data);.
Pass your object A (as this) into B, such as on doSomething(this), changing the signature of doSomething to doSomething(YourInterface callback).
In B you may then call callback.callbackMethod(data), processing data within your Activity A.
Related
I seem to be stuck with a problem with an object communicating with my activity class. The object is a view object with an onClick method that when called I would like it to notify my activity class so that it can perform said action. Below is some example code of my situation (assume all conventional setup operations have already been made):
public class MainActivity extends AppCompatActivity{
//...other global methods and objects
//Does not have access to instantiated Entry object(s)
public void entryObjectWasClicked(){
//perform said action
}
}
public class Entry extends View implements View.OnClickListener{
//...other global methods and objects
//Does not have access to the MainActivity object
#Override
public void onClick(View v){
//send a message to the MainActivity to
//somehow call the entryObjectWasClicked() method
}
}
The only way (off the top of my head) that I could think about dealing with this problem is by creating a static method in MainActivity and then calling it from an anonymous MainActivity object in the onClick method of Entry. The problem with the static method approach is that any subsequent method/object/primitive usages in the static method force those methods/objects/primitives to be static. This defeats the purpose of then being able to have two different instances of the MainActivity object.
After some looking I came across using Broadcast messages, specifically using the LocalBroadcastManager to send an intent to the activity. This code example works for my model, but I want to know: is this the best way for me to go about sending messages to my MainActivity from my Entry object?
If there is a more effective way of doing all this, what would it be?
You're overcomplicating things. Don't override onClick for this. Instead, have your activity call setOnClickHandler on your view, which sets a callback that's called when the view is clicked. Then use the default implementation.
Since you extend view, i guess you want to use it inside a layout. That means you may want to create a Listener for that. Example:
public class Entry extends View implements View.OnClickListener{
private OnClickListener listener;
public void setListener(OnClickListener listener) {
this.listener = listener;
}
#Override
public void onClick(){
if (this.listener != null) this.listener.onClick(this);
}
}
How you can inflate your layout in your Activity and access your custom view.
public class MainActivity extends AppCompatActivity{
public void onCreate( ...) {
Entry entry = findViewById(R.id.entry);
entry.setListener(new OnClickListener(...));
}
}
At school we're now learning on how to make fragments more universal by using interfaces.
This technique is still kinda abstract and I don't really know when/how to use it.
Can anybody point me to some resources on how to use that technique (Could it be called interface callbacks?)
All help is very appreciated!
The callback approach, as you would call it, is as simple as Listener interface found in many parts of Java or Android. You may check the Observer pattern if you want to learn about a very general description. But if you already understand how to work with Listener, you will easily get the point about callbacks.
NOTE: Do not mix it with Callback term - these are not the same.
Suppose we have Activity MyActivity and Fragment MyFragment. We want to post some data from Fragment to Activity. Then let us create an interface within MyFragment:
public class MyFragment extends Fragment{
private PostDataCallback mCallback;//our Activity will implement this
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (PostDataCallback) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
public interface PostDataCallback{
public void onPostData(Object data);
}
/*
we trigger this method when we calculated
data or something like that and want to post it*/
public void onSomeEvent(Object data){
mCallback.onPostData(data);
}
}
Our MyActivity will look like this:
public class MyActivity extends Activity implements MyFragment.PostDataCallback{
private Object data;
#Override
protected void onCreate(Bundle savedInstanceState){
getFragmentManager().beginTransaction().add(R.id.some_container_id, new MyFragment(), "my fragment");
}
#Override
public void onPostData(Object data){
this.data = data;
//some operations
}
}
So, MyFragment knows nothing about the implementation of it's callback. But it knows, that it can call the method onPostData(Object o) on the instance of PostDataCallback, which is held in the variable mCallback.
Thus, when MyFragment triggers it's mCallback.onPostData(data), MyActivity get's the result.
Exactly the same approach would work if we wanted to send message from MyActivity to MyFragment, but we would do it do it vice versa: the trigger method, callback interface definition and instance would reside in MyActivity, and MyFragment would implement the interface.
Here are steps:
Download sample data from http://developer.android.com/training/basics/fragments/index.html(given in right side) and also look at url to how to add fragments from xml or dynamically to performing fragment transaction operations..
Then would recommend you to go through with fragment guide..http://developer.android.com/guide/components/fragments.html
Once you understand complete life cycle and its fragment callback methods then would be easy to understand example given by Google as sample.
To defining interface in fragment to calling interface or passing callback to activity..
Let’s say you have two fragments which shows list as article titles and article details.
In your article list extends fragment list public class Fragment1 extends ListFragment
Set your list view using list adapter in oncreateview method.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, Array);
setListAdapter(adapter);
Now we need to display article details when user click on article, so we need to pass position to activity to it can call back corresponding article details to show in fragment2.
So when user click on article, system call onListItemClick callback method.
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Call interface here and pass article position
Define interface and pass position in method which activity will override.
public interface OnArticleSelectedListener {
public void onArticleSelected(int position);
}
In on attach method instantiates an instance of interface by casting the Activity, If the activity has not implemented the interface, then the fragment throws a ClassCastException. On success.
Override interface method to display article details by passing position as bundle data to Fragment2.
Hope it will help you to understand sample code.
You can simple create new Android Application project in eclipse.
Then create Android Object (Fragment) with callback methods. This will give you an idea for interfaces.
And then the same you can apply for activity to fragment.
I have defined a function in MainActivity now I want to access the function from another class in my app. I have created an object of the MainActivity and with that object I have called the function. Although there is no error, it's not executing. Every time I try to execute, the app crashes.
Activity A should have a variable
static ActivityA activityA;
In onCreate state:
activityA = this;
and add this method:
public static ActivityA getInstance(){
return activityA;
}
In activity B, call
ActivityA.getInstance().myFunction(); //call myFunction using activityA
You cannot just create objects of Activities by using:
MyActivity activity = new MyActivity();
as you would with normal Java classes. All Activities in Android must go through the Activity lifecycle so that they have a valid context attached to them.
By treating an Activity as a normal Java class, you end up with a null context. As most methods in an Activity are called on its Context, you will get a null pointer exception, which is why your app crashes.
Instead, move all such methods which need to be called from other classes into a Utility class which accepts a valid context in its constructor, and then use that context in the methods to do the work.
Make the variable public and then create object in adapter like this:
public int i; // Variable in Activity class
((ActivityName) context).i // accessing in adapter
I'm dealing with fragments.
I have an Activity and different fragments.
Each fragment need the access to a Class(call it X) that allow it to access a database, but, because I have a lot of fragments, I don't want to create a different instance of the Class X in every fragment as I think it will require lots of memory.
So how can I do?
I wrote something like this (with a getter), but it doesn't work!
public class MyActivity {
private ClassX classx;
.....
public ClassX getClassX() {
return classx;
}
.....
}
But than, how can I call it from the fragment?
From the fragment call your activity's method
((MyActivity ) getActivity()).getClassX() ;
This is a little bit more of a Java question and android.
If you looking at accessing the database, look at creating a database singleton.
So something like:
public class Database {
// This starts off null
private static Database mInstance;
/**
* Singleton method, will return the same object each time.
*/
public static final Database getInstance() {
// First time this method is called by Database.getInstance() from anywhere
// in your App. It will create this Object once.
if(mInstance == null) mInstance = new Database();
// Returns the created object from a statically assigned field so its never
// destroyed until you do it manually.
return mInstance;
}
//Private constructor to stop you from creating this object by accident
private Database(){
//Init db object
}
}
So then from your fragments and activities you can then place the following field in your class's (Better use use a base activity and fragment to save you repeating code).
public abstract class BaseFragment extends Fragment {
protected final Database mDatabase = Database.getInstance();
}
Then your concrete fragments can extend your BaseFragment e.g. SearchListFragment extends BaseFragment
Hope this helps.
Worth reading about singletons and database
Regards,
Chris
Define an interface called Callbacks (or something else if you want). In it, have a public method called getClassX(). Then make your Activity implement the Callbacks interface.
In your Fragments, in onAttach, store a reference to a Callbacks object (i.e. your activity via something like:
if(activity instanceof Callbacks)
mCallbacks = (Callbacks)activity;
This will guarantee that the Fragments are able to call the function. (in case you want to reuse the fragments later in another app)
Then in your Activity, in onCreate(), create an instance of ClassX. In your getClassX() method, just return a reference to it.
When you want a reference to it from your Fragments, call mCallbacks.getClassX() and you should be sorted.
You can use a static object in your activity, and use it from the fragment, or call the getActivity() method in your fragment to access the whole activity objects/methods
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.