How to finish an Activity that is used in a TabSpec, as the child of TabHost - android-activity

I have Main Activity which contains a TabHost.
In the TabHost I have several TabSpec which use an Intent for the content of the tab.
At certain points in my code I need to remove a tab from the TabHost, and finish the Activity that was in that tab's TabSpec.
I am able to remove the tab from the TabHost, but as soon as I call finish on that child Activity, the Main Activity terminates. I have even tried calling finish some time later, with a timer. It still kills the main activity.
How can I finish a child activity without killing the main activity?

Tab Host was decrapated by google so you shouldnt use it anymore you should replace it using actionbarsherlock its a better option for tabs.

Related

what is the difference between ActivityStack and TaskRecord

I'm studying with AOSP, and I found ActivityStack and TaskRecord in "ActivityStack" Class. There is explanation In https://developer.android.com/guide/components/tasks-and-back-stack , Back-stack(=Activity Stack) And Task seems similar to me... What is the the difference between ActivityStack and TaskRecord?
In this https://developer.android.com/guide/components/tasks-and-back-stack,
Focus on below lines, For Task
A task is a cohesive unit that can move to the "background" when users begin a new task or go to the Home screen, via the Home button. While in the background, all the activities in the task are stopped.
For back stack
The back stack for the task remains intact—the task has simply lost focus while another task takes place. A task can then return to the "foreground" so users can pick up where they left off.
For info you can refer below links:-
What is the relationship between Task and Back stack
https://blog.mindorks.com/android-task-and-back-stack-review-5017f2c18196
https://medium.com/google-developers/tasks-and-the-back-stack-dbb7c3b0f6d4
If you think of activity back stack as two levels, it might be easier to understand the purpose of ActivityStack. Android supports launchMode and taskAffinity to put activities into different TaskRecords. But even activities are put into different TaskRecords, it keeps supporting the back button to switch back to previous activity. So when you launch activity that needs to be in new TaskRecord, then back button is pressed, it switches to top activity of previous TaskRecord. So ActivityStack is more like a TaskRecord stack, and TaskRecord is more like the activity stack inside the TaskRecord, however, general speaking, ActivityStack controls the pop up sequence, and you can say it's an indirect activity stack.
And creating ActivityStack seems to make management easier logically in multiple window environment. If you enable free form in Android, each launched window mode app has its own free form stack, and each stack has its own back stack.
My 2c.

Finish activity onPause but still be in backstack?

I'm trying to minimize memory usage in my app, and one of the things I'm doing is calling finish() in the onPause method (which I know is not the best way to do things). For the most part, it seems to be working well, but when the user clicks the back button from the next activity, it logically skips over the finished activity and goes back further. Is it possible to have that activity in the back stack and just get recreated if the user presses back?
No. This conclusion comes from the task and backstack documentation as well as the activity documentation and a general understanding of how a stack data structure works.
A stack data strucure only has 2 possible operations push/put, which adds something to the collection, and pop, which removes it. Stacks folow a last in first out model, or LIFO, where by last thing added - in your case an activity - is the first thing removed when pop is called.
Within the android lifecycle activities are generally popped from the stack when the back button is pressed. At that point onDestroy() is called and the activity is removed (you can verify this by overriding the onDestroy() method and logging the results if you want to check). Alternativly you can force onDestroy() to be called by calling finish() as you are. Finishing an activity effectivly does the same thing as pressing back. The activity is destroyed and must be recreated before it can be added to the stack.
For what you're trying to do the stack would have to incorporate some intermediate state in which an activity does not exist but rather something akin to a reference is held that, when moved to the top, would indicate that the corresponding activity should be recreated. Since this is not how the sack works - it only holds activities - that state cannont exist and so the result you are talking about is not possible.
Your Goal is to minimize memory usage,Just make use of activity life cycle, You can do this alternative(if you need)
-Just leave onCreate() method blank.(only do setContentView(layout))
-Override onResume();
-whatever you were doing in onCreate just copy paste to onResume().
-and In onPause(), Recycle your all bitmaps and set them to null(I think you are using Bitmaps thats why you are very cautious about it ). and remove your views.
Now what will happen, when you launch your new activity, onPause() would be called. that will remove your all bitmap and views. and when you come back, onResume() will be call.(onCreate will not be called). and that will again initialize your view and bitmaps.
No, i don't think that is possible. Once you finish the Activity it's gone. You could, however, implement and handle your own stack. On back pressed, you would just start the closed Activity again.

How do I implement "Cancel" button inside the method building data source in ModelController.m for Page View Controller

I have a Page View Controller that's implemented in 3 files. One of them, the ModelController.m implements "generateData" method, which basically just builds and formats all the pages for this Page View Controller. Inside this method, the first thing I do is I create a Progress Bar popup with "Cancel" button. Then, inside the while() loop, I keep building the pages and at the same time, every 10th page, I update the progress bar for the user to see that the application is still generating the output.
Once the "generateData" method completes, i.e. builds all the pages (and there may be over 1,000 or even 10,000 pages depending on user input), it returns "self" to a method inside RootViewController.m, which in turn passes that generated data in "dataObject" to "viewWillAppear" in DataViewController.m, which finally displays pages in that object to the user.
It all works great, except the "Cancel" button. Because "generateData" method runs on the main thread, it blocks and the "Cancel" button becomes totally unresponsive. By "blocks" I of course mean it takes all CPU cycles, not allowing anyting else to execute, and it may take over a minute to generate 10,000 pages so I really want to allow the user to cancel the operation.
I tried to create a separate thread for the Progress Bar popup which contains Cancel button, but that won't work because all UI operations need to be performed on the application's main thread.
What almost seems to work, is when I put the "generateData" method on a separate thread and keep the Progress Bar on the main thread. This would work just fine, except that now "generateData" is put on another thread to execute in the background and returns immediately, hence returning empty "self" or rather empty "dataObject", causing a crash because there is nothing in that object yet to display.
So how can I check if the "generateData" thread is done, and "return self" ONLY when it's done? I can't really have some BOOL true/false variable and do it in a loop, because that loop on the main thread would be again blocking the "Cancel" button.
Or, alternatively, what is the correct way to implement the "Cancel" button on a lengthy method in iOS? Maybe I'm doing it all wrong, but for the life of me I can't find the right recipe for this.
Thank you in advance for the help, the code is rather extensive and that's why I didn't include any, but I hope my description gives you a good idea of what's going on. I can provide code if that would help.
The correct way to do this is to load the data asynchronously (on a background thread) and update the main (UI) thread to update the progress bar, etc... But you probably don't need a progress bar since you can probably load those pages faster than a user can flip them, so load 100 and let the user play while you continue to load the next 99,900... Except those may not be the exact numbers you should use....
If you continue to use the progress view and cancel button, then you would cancel the background thread when the user presses "Cancel", which would respond since your data generation is on a background thread...
Look into either Grand Central Dispatch or NSInvocationOperations
Here's a good tutorial by Ray Wenderlich to get you started.

how to call previous activity in android?

I have five activity in my app,
Act1->Act2->Act3->Act4->Act5,
All activity goes in single direction as I have stated above,
Now I have to call again Act2 after successful completion of my Act5's task, so its working good and showing me the Act2 (I have Used startActivity(callIntent) in Act5 for showing me Act2 again),
After this when I click on Back button in Act2, I have Act1 (I have Used startActivity(callIntent) in Act2 for showing me Act1 again) its what I want .....
But the problem is that when I click Act1's back button it is going to put me on Act2. But I want to exit from there, because Act1 is the first initial activity.
How Can I set focus to my hidden activity , instead of creating Intent and call startActivity.
Any idea? Please help.
After long research I got pretty much understanding of "back stack" for all the activities in an app.
Each time I moved to another activity and also for opening previous activity I have used Intent.startActivity() with flag FLAG_ACTIVITY_NEW_TASK, So every time I have new activity added in the "back-stack".
I have tried intent flag as FLAG_ACTIVITY_CLEAR_TOP while calling previous activity from "back-stack" using Intent.startActivity() and I got the solution of calling back the previous activity and clears all stack top activity above the calling one activity. So now back button does working nice as I needed.
Let see My problem of calling previous activity ,
A = activity; A1->A2->A3->A4->A5->B2 , now if you click on back button you will have A1 activity , and after clicking on A1's back button you have again B2 activity which was called after A5 and so on.
After using the FLAG_ACTIVITY_CLEAR_TOP in A5 activity and called again A2 (Not creating new activity but calling precious one) I have following situation.
A = activity; A1->A2->A3->A4->A5
calling previous A2 activity, and I have following scenario.
A1->A2 only.
Thanks.
Instead of following code (with flag Intent.FLAG_ACTIVITY_NEW_TASK):
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setClass(CurrentActivity.this,PreviousActivity.class);
startActivity(callIntent);
Try using following one with Intent.FLAG_ACTIVITY_CLEAR_TOP
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
callIntent.setClass(CurrentActivity.this,PreviousActivity.class);
startActivity(callIntent);

How do I access the toolbar item (org.eclipse.swt.widgets.ToolItem) from within the Activator?

I'm implementing a simple eclipse notification plugin that is supposed to change an icon in the toolbar if something of some nature happens. I made an extension to org.eclipse.ui.menus and the icon shows up nicely.
I thought of starting a poller thread in the Activator and have it poll every couple minutes and changing the icon accordingly.
The thread must have access to the ToolItem in order to call setImage(). How do I access the ToolItem to pass it on to the Thread?
Your handler must implement org.eclipse.ui.commands.IElementUpdater. It can call org.eclipse.ui.menus.UIElement.setIcon(ImageDescriptor). When you need to update the image, you call org.eclipse.ui.commands.ICommandService.refreshElements(String, Map) to trigger the refresh and the call to your handler.