I have an issue where I need to access a method in my Activity from Android AsyncTask's onPostExecute() method
I have 2 Activities both contain a common method as below:
(1) Activity1 -- > refreshUI()
(2) Activity2 ----> refreshUI()
I got one AsyncTask call GetDataAsyncTask(Activity a ) which takes calling activity as argument
Now from my activity1 I will call new GetDataAsyncTask(Activity1.this).execute.
Same as above from my activity2 I will call new GetDataAsyncTask(Activity2.this).execute.
My AsyncTask is as below :
public class GetDataAsyncTask extends AsyncTask<String ,Void , String> {
public Activity context;
public PostAsyncTaskHelper(Activity c) {
context = c;
}
protected String doInBackground(String... arg0) {
// Webservice calls
}
protected void onPostExecute(String result) {
if(result.equals("qq")) {
//Where I am not able to access refreshUI()
//method of any one of my activities
context.refreshUI()
}
}
}
Can anyone help me how to get reference of any of the called activities from AsyncTask?
Make an interface that has the method refreshUI(), and make both Activity1 and Activity2 implement it. Then, you just need to typecast context to the type of the interface.
Also, you need to be careful about holding a reference to an Activity from inside an AsyncTask, because in the case of a config change (like screen rotation), you'll be holding on to a destroyed Activity instance. See here for details, and the corresponding example solution to this.
Define an interface for your Activities
public interface MyActivityRefreshInterface
{
public void refreshUI();
}
your Activities must be defined as implements MyActivityRefreshInterface.
Your onPostExecute can then cast the context as (MyActivityRefreshInterface)context
Because refreshUI is not a method in Activity. It is in your particular Acivity1 and Activity 2 classes, not the Activity class from Android. You should refactor so Activity1 and Activity2 to inherit from BaseActivity that has the refreshUI method on it and mark context in the AsyncTask as a BaseActivity
Related
i have a setting Activity that store name , by changing the name it must first send that to my server and if its store in server successfully then it should set in the summary of my EditTextPreference .
everything works fine but at the end i cant touch the EditTextPreference to set name on it.
this method is in setting activity but called from onPostExecute of the AsyncTask
public void setNewSetting(Activity activity) {
EditTextPreference editTextPreference = (EditTextPreference) UserSettingActivity.this.findPreference(activity.getString(R.string.pref_name_key));
name = sharedPreferences.getString(activity.getString(R.string.pref_name_key), "");
editTextPreference.setSummary(name);
}
the activity is the setting activity that i passed to the AsyncTask and then passed to method.
my problem is here and give me a nullPoiterException for EditTextPreferences
Sorry for my bad english.
and thanks in advance.
Method 1:
If activity is still in background, pass your context to AsyncTask and create an instance of your Settings Activity.
SettingsActivity settingsActivity = (SettingsActivity) context;
then, call the method in onPostExecute()
settingsActivity.setNewSetting();
And, have your setNewSetting() method in your SettingsActivity. It should be public and put some checks for null values.
Method 2:
Use an interface delegate. Create an interface:
public interface TaskListener {
void onComplete();
}
Pass it to AsyncTask when you execute it, something like:
new MyAsyncTask(params, params, new TaskListener() {
#Override
public void onComplete () {
// call setNewSetting from within SettingsActivity
}
}).execute();
You get it in your AsyncTask constructer:
public MyAsyncTask (String params, String param2, TaskListener taskListenerDelegate) {
this.taskListenerDelegate = taskListenerDelegate;
}
Call its onComplete() in onPostExecute() :
taskListenerDelegate.onComplete();
Method 3
Not recommended, but you can try with startActivityForResult() too. And, listen in onActivityResult() to apply changes.
I have been struggling with this problem for two days,I am in situation where i need to use a method in ActivityB from ActivityA . The problems lays in getting the context of A i have tried many solutions like:
static ActivityA activityA;
In onCreate state:
activityA = this;
and add this method:
public static ActivityA getInstance(){
return activityA;
}
In ActivityB, call
ActivityA.getInstance().myFunction(); //call myFunction using activityA
it did not work out because this need the ActivityA to be instantiated in order to pass its context to A but this is not accomplishable in my case is there any way of getting an activity's context without switching activities .
my question might turn out to be simple or intuitive but im new to this concept , thanks in advance
As you want to have common functionality in both activities, you can create BaseActivity that extends Activity and define your method in that and extend ActivityA and ActivityB by BaseActivity then you can access methods.
You can do it like this,
public class BaseActivity extends Activity
{
public void myFunction()
{
...
}
}
And do this for other activities:
public class ActivityA extends BaseActivity
{
public void someMethod()
{
myFunction(); // you can call function here directly
}
}
You could extent class A using Class B simply
OR
public static ActivityA activityA;
In onCreate state:
{
activityA = this;
}
Outside Oncreate
public myFunction{
}
and in ActivityB call
activityA.myFunction();
Here I Created Two Classes Consider as Activities , And Then Created one Public methodA() in class Activity_A , then Created Class Activity_B and Created methodB() , And Created Object of Activity_A and Called methodA() by passing context of Activity Activity_B .
class Activity_A{
public void methodA(Context context){
Toast.makeText(context,"methodA",Toast.LENGTH_LONG).show();
}
}
class Activity_B{
public void methodB(){
Activity_A activity_a = new Activity_A();
activity_a.methodA(Activity_B.this);
}
}
There are two options:
1) Add the static keyword to your shared methods
OR
2) You can try reflection.
For reference follow the link:
What is reflection and why is it useful?
Im trying to figure a way how to call an activity that an adapter has started. Is there a way to get the instance of the activity from startactivity and make a method call into the activity ?
I'ved got an adapter that has a list
public class LanguageDownloadRVAdapter extends RecyclerView.Adapter<LanguageDownloadRVAdapter.DownloadViewHolder>{
And in this adapter, it starts a particular activity called MainActivity
context.startActivity(new Intent(context, MainActivity.class));
((Activity)context).finish();
Here is the MainActivity that it starts
public class MainActivity extends AppCompatActivity implements IabBroadcastListener{
How can I make a call from the adapter to a method in the MainActivity. (im just trying to perform inapp purchase which is implemented in the MainActivity). so how can i do something like this.
mainactivity.perform_inapp_purchase();
Try to use EventBus for passing data between activity and list adapter. You can do it in the same way for passing data between activity and fragment.
This work the same way as storing data in global variable (in a fancier way)
In the adapter:
Add a new Field private Context mContext;
In the adapter Constructor add one more parameter as below, and assign it into class level variable:
public LanguageDownloadRVAdapter(......,Context context){
//your code.
this.mContext=context;
}
In the Adapter where you want to call Activity's perform_inapp_purchase() method:
if(mContext instanceof MainActivity){
((MainActivity) mContext).perform_inapp_purchase();
}
More Generalized Approach:
If you need to use this same adapter for more than one activity then :
Create an Interface
public interface InAppPerchaceInterface{
void perform_inapp_purchase();
}
Implement this interface in activities
Then in Adapter, call like below:
if(mContext instanceof InAppPerchaceInterface){
((InAppPerchaceInterface) mContext).perform_inapp_purchase();
}
You can store the instance in the application class, but you should be careful about the memory leaks.
In the onCreate of your activity
protected void onCreate(Bundle savedInstanceState)
{
// get the instance using this and store it in the application class or in the place that you want to call from it
}
From where will you call your method?
I didn't understand the situation.
i have a tabActivity that hold 3 tabs.
from one tab i want to open another tab and run a method that refresh the data.
i use this method to switch tabs
public void switchTabInActivity(int indexTabToSwitchTo) {
MyTabsActivity ParentActivity;
ParentActivity = (MyTabsActivity) this.getParent();
ParentActivity.switchTab(indexTabToSwitchTo);
}
to open the tab but i cant' call the method.
any ideas?
According to me, I believe what you are doing here is correct, but still you are not doing the entire flow. Let me explain,
Calling the above method will redirect you to that particular tab. But what you actually have to do is to execute some method in that class. But were are you calling that method.
Consider a Activity with onCreate(),
you could have called that method in your onCreate(). But now when you execute your
public void switchTabInActivity(int indexTabToSwitchTo) {
MyTabsActivity ParentActivity;
ParentActivity = (MyTabsActivity) this.getParent();
ParentActivity.switchTab(indexTabToSwitchTo);
}
method, this will call the onResume() of that activity. So my suggestion would be to override the onResume method of your particular activity which has that method..
you can simply create a static method which can be easily call by using ClassName.methodName();
see example,
public class myAnotherClass
{
public static void accessFromAnotherClass()
{
System.out.println ( "I am accessed publically" );
}
}
// Now Accessing above class method from another class file
public class myFirstClass
{
private void myClassMethod()
{
myAnotherClass.accessFromAnotherClass(); // called from another class. in your case , another tab.
}
}
I start ASyncTask from the Activity:
public class PrepareRequestTokenActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new OAuthRequestTokenTask(this, consumer, provider).execute();
}
Then, depending on result of ASyncTask execution I should either close this PrepareRequestTokenActivity activity on not.
(Result is known to onPostExecute of AsyncTask)
onPostExecute you simple use your this variable to execute finish().
in your constructor keep your activity reference
and call finish() in onPostExcecute method
If you're working from within onPostExecute, and you're asyncTask() class is internal to your activity; simply calling MyClassName.this.finish() , or something alike, should work just fine? The onPostExecute(), I believe, has UI scope.