Consider the following scenario:
The class TemplateActivity extends Activity. Within onResume() it performs a validation of a boolean variable then, if false, it finishes the method and the activity, and starts a new activity, OtherActivity.
When the class ChildActivity, which extends TemplateActivity, runs, it waits for super.onResume() to finish and then continue no matter if its super needs to start the Intent or not.
The question:
Is there a way to terminate the ChildActivity when the OtherActivity needs to start from the TemplateActivity? Without implementing the validity check in the child class.
Superclass:
class TemplateActivity extends Activity {
#Override
protected void onResume() {
super.onResume();
if(!initialized)
{
startActivity(new Intent(this, OtherActivity.class));
finish();
return;
}
//Do stuff
}
}
Subclass:
class ChildActivity extends TemplateActivity {
#Override
protected void onResume() {
super.onResume();
//Do stuff
}
}
A more elegant solution would be a slightly different approach to the class design:
Introduce a method DoStuff() (replace with sensible name) in the TemplateActivity . Do all the // do stuff bits there.
Call this method from the end of TemplateActivity OnResume
Override it in the child activity to extend it with the child activity // do stuff bits.
Do not override onResume in the ChildActivity.
This way, if the condition fires in TemplateActivity OnResume, none of the parent and child DoStuff will be done. The ChildActivityshouldn't have to know anything about this behavior.
I guess this is what you're trying to get:
class ChildActivity extends TemplateActivity {
#Override
protected void onResume() {
super.onResume();
if (!isFinishing()) {
// Do stuff
}
}
}
Related
I think this question may simple but I didn't find any solution for this,
I there any way in Android that if any one of an activity calls onPause() I need to show Toast message or any notification kind of thing need to show. Generally I want to get notified when activity calls onPause() but I need it in one place since I may have some 15 activity I don't want to add it in all the activity.
ex:If I have activity when any one of the activity calls onPause I need to get notified but that notification code should be in one place and we should not add any line of code onPause() Is it possible to do this.
Thanks.
Create a baseActivity, which has for example :
open class BaseActivity : AppCompatActivity() {
override fun onPause() {
super.onPause()
Toast.makeText(this, "notified", Toast.LENGTH_SHORT).show()
}
}
Then you can extends this in your activities and handle the on pause call in BaseActivity
If your minSdkVersion >= 14, you can use Application.ActivityLifecycleCallbacks: ActivityLifecycleCallbacks
You have to define a custom Application class and you can register for this callbacks afterwards:
public class MyApplication extends Application {
private class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
#Override
public void onActivityCreated(final Activity activity, final Bundle savedInstanceState) {
//nothing to do
}
#Override
public void onActivityDestroyed(final Activity activity) {
//nothing to do
}
#Override
public void onActivityPaused(final Activity activity) {
// TODO Do your stuff, e.g. show toast.
}
#Override
public void onActivityResumed(final Activity activity) {
//nothing to do
}
#Override
public void onActivitySaveInstanceState(final Activity activity, final Bundle outState) {
//nothing to do
}
#Override
public void onActivityStarted(final Activity activity) {
}
#Override
public void onActivityStopped(final Activity activity) {
}
}
private final LifecycleCallbacks callbacks;
public void onCreate() {
super.onCreate();
callbacks = new LifecycleCallbacks();
application.registerActivityLifecycleCallbacks(callbacks);
}
}
Create a BaseActivity which contain all the methods you want to use in all other activities.
Then extend every activity with BaseActivity to call onPause() method.
I tried several times to invoke Resume method of MainActivity from the Fragment,
calling simply onResume(); nothing in result.
code for resume method
protected void onResume() {
all.clear();
outgoing.clear();
incoming.clear();
getFromSdcard();
super.onResume();
}
I want to call this method from fragment.
Enhancing #cricket_007 response :
You can invoke onResume from the parent Activity, but just like you have seen, onResume has protected access blocking you from calling it.
There is a small visibility workaround that allows you to do it.
1 - Implement this method on your activity
public void myOnResume(){
this.onResume();
}
2 - Then on your fragment you can invoke
public void myFragmentMethod(){
// make sure to double check casts (to YourActivity) like these before invoking
((YourActivity) getActivity()).myOnResume();
}
Conclusion and recommendation : Even though it is not recommended that you implement it this way, it can be done like I said.
In my opinion, what you should do is :
1 - Have all the functionalities of your onResume() method inside a proper method of your own (you name it!) like :
public void clearData() {
all.clear();
outgoing.clear();
incoming.clear();
getFromSdcard();
}
2 - Then you could just separate all these functionalities from onResume() and still have them invoked like
protected void onResume() {
super.onResume();
clearData();
}
3 - Invoke it on your fragment like (previously shown)
public void myFragmentMethod(){
// make sure to double check casts (to YourActivity) like these before invoking
((YourActivity) getActivity()).clearData();
}
Let me know how it went.
Regards,
You are calling the Fragments onResume()
You can try getActivity().onResume(), but you really should make a method to do whatever code you need rather than explicitly call lifecycle methods.
Create an Interface
interface OnParentActivityResumed {
fun onActivityResumed()
}
implement the interface in the fragment
class MyFragment: Fragment(), OnParentActivityResumed{
override fun onActivityResumed() {
//[YOUR CODE WHEN PARENT ACTIVITY RESUMED]
}
}
on parent activity onResume add
override fun onResume() {
super.onResume()
myFragment.onActivityResumed()
}
I have a MainActivity, SecondaryActivity and an AsyncTask class.
MainActivity has a method called doSomething()
I call the AsyncTask from MainActivity like this:
new asyncTask(MainActivity.this).execute();
Which means I can reference the MainActivity in my onPostExecute
#Override
protected void onPostExecute(Boolean result){
super.onPostExecute(result);
# activity is defined as this.activity
activity.doSomething();
}
How can I call the AsyncTask from my SecondaryActivity in a similar manner, because I'd need a reference to my MainActivity to access its methods?
EDIT: I would want the doSomething() to be called at all times. So even if it's from SecondActivity, once it finishes its background operation -> doSomething()
The method I'm calling refreshes the screen of MainActivity to show data changes. Secondary activity only calls the AsyncTask when it is being paused/stopped/destroyed but currently the Asynctask finishes after MainActivity has started and so the changes aren't visible.
I think your AsyncTask in nested in the MainActivity currently. Its better you put it in separate class. Whatever parameter is required by it pass it in its constructor. Let both your activity implement the same interface. Something like this
class MainActivity/SecondaryActivity implements DoSomethingListener {
void doSomething() {
}
}
Also pass your activity reference to AsyncTask in the constructor.
Finally onPostExecute since you have reference to either MainActivity or Secondary Activity. Call activity.doSomething.
I guess you want to update something in MainActivity based on the result of the AsyncTask called from SecondaryActivity. In that case, I'd suggest calling SecondaryActivity with startActivityForResult. Then in your onPostExecute, call setResult to set a flag or some data.
Finally, in MainActivity override onActivityResult to call doSomething when the request code corresponds to SecondaryActivity.
So your requirement is to have a single instance of MainActivity. Data in MainActivity may be updated from within MainActivity or from SecondaryActivity. In either case the data to be updated is obtained using an AsyncTask.
My Suggestion
Add the following to the MainActivity in manifest, (More about android:launchMode here.)
android:launchMode="singleInstance"
When you are done interacting with SecondaryActivity, do this,
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("DATA1", "your_data1");
intent.putExtra("DATA2", "your_data2");
startActivity(intent);
finish();
Then in your MainActivity,
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String data1 = intent.getStringExtra("DATA1");
String data2 = intent.getStringExtra("DATA2");
}
Then call AsyncTask in MainActivity using data1 and data2.
NOTE: This is one way to approach your problem. There are other approaches such as startActivityForResult() depending on your requirement.
UPDATE
If you want to cancel your AsyncTask, call asyncTask.cancel(true);
However, this will not ensure your HttpRequest is aborted, as the cancel will take effect after the request has completed. The work-around for this is a bit hackish. After calling cancel(), contineously check if isCancelled() is true, then do httpRequest.abort() This will only be the fastest way to finish your async task. Need not necessarily mean the request gets aborted.
Try this in your UpsertTask class.
private Context mContext;
public UpsertTask(Context context){
mContext = context;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
if(mContext instanceof MainActivity){
((MainActivity) mContext).doSomething();
}
else if(mContext instanceof SecondActivity){
((SecondActivity) mContext).doSomethingElse();
}
}
#Override
protected void onPostExecute(Boolean result){
super.onPostExecute(result);
# activity is defined as this.activity
if (activity != null) {
if(activity instanceof MainActivity) {
activity.doSomething();
} else if(activity instanceof SecondaryActivity) {
activity.doSomethingElse();
}
}
}
I think that would work. (if you understand your question correctly).
One way this could be done is by using an event bus. This is a way of passing messages/data between activities. You can post to the bus and then activities can listen for the message if they register.
EventBus class (seperate)
public class EventBus extends Bus {
private static final EventBus bus = new EventBus();
public static Bus getInstance() { return bus; }
private EventBus() {}
}
MainActivity class
...
#Override
protected void onResume() {
super.onResume();
EventBus.getInstance().register(this);
}
#Override
protected void onPause() {
super.onPause();
EventBus.getInstance().unregister(this);
}
#Subscribe
public void asyncDone(String message) {
foo(message)
}
AsyncTask class
...
#Override
protected void onPostExecute(Boolean result){
super.onPostExecute(result);
EventBus.getInstance().post("My data")
Thanks to #theheartbreakpug from Reddit for giving me this solution.
I'm designing an architecture where the app needs to execute certain set of operations everytime it goes to background (onPause) and a set of operations everytime it comes back to foreground (onResume), irrespective of the activity (for all the activities). Is there a way with which I can achieve this, without having to call those methods in every activity class' onPause and onResume overrides?
Make your own class that extends Activity and add your desired behavior to its onPause and onResume methods.
Then you extend that class on your activities.
public class BaseActivity extends Activity {
#Override
protected void onPause() {
// ...
}
#Override
protected void onResume() {
// ...
}
}
public class Activity1 extends BaseActivity {
// ...
}
You could extends your Activities by a BaseActivity which extends Activity, and create the two methods onPause / onResume in it.
See this answer for more information.
What happens when finish() method is called in onStop() method?
Does it causes anr : means it calls
onPause()->onStop()->finish()->onPause()....
or it finishes the activity : means it calls directly
onDestroy()
Actually, I want to finish my activity when it is completely invisible.
EDIT:
See this scenario, I launch an activity B whose layout height and
width is smaller than activity A, so activity A is partially visible
and when I press the home button activity A becomes completely
invisible. At this point I want to close activity A, so that it do not
call onRestart().
Thanks in advance.
It finishes the activity and onDestroy() is called. If you want to finish your activity when it is invisible then you should call finish() in onStop().
according to your scenario, maintain one flag in MainActivity indicating that other Activity is launched or not? and make sure yourself to finish MainActivity or not based on that flag ...
this may help you...
public class MyActivity extends Activity {
private boolean isSecondActivityLaunched;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
isSecondActivityLaunched = false;
}
public void onClick(View view) {
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
isSecondActivityLaunched = true;
}
#Override
protected void onStop() {
super.onStop();
if(!isSecondActivityLaunched) {
finish();
}
}
}
It will be best way in your case to call finish() ;
Thanks