问题
I am developing an application that will be used in an industrial setting as a handheld interface, distributed and preconfigured by my workplace. I am working on making the application run as the Home Launcher so that there will be less temptation for the tablets to "go missing".
BACKGROUND
I have the following in my manifest to make the application a Launcher:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
(I can post more of the manifest if necessary)
My application's structure is as follows:
- USB_Stuff extends Activity
- Main extends USB_Stuff
- UIs extends Fragment
- SQLiteHelper extends SQLiteOpenHelper
The "Main" handles all of the fragment communications and transactions. The "Main" is also what is registered in the manifest under the <activity>
name attribute.
I also have a BOOT_COMPLETED
receiver within the manifest that launches my application.
PROBLEM
SOLVED Now everything works great if I run the program from Eclipse and work with it. However, if I reboot the device (tested on both Asus Nexus 7 (4.2.2) and Samsung Galaxy Tab 2 7.0 (4.1.1)) it starts up on the first screen, which contains a ListView
as follows:
I can then choose an item form the list and it will take me to the next fragment that contains three buttons in place of the list:
SOLVED If I click within the red boxes on the second image above, then I can select a different item form the ListView
up to one time, after I touch in the red space once it deactivates the "onClickListener"(?). Although if I click on one of the three visible buttons, the application performs it's onClick
method instead of clicking through to the previous screen. This behavior continues on for multiple screens and stops once the application reaches the TableLayouts
.
Another issue, that I feel may be related, is that the back button and my later cancel buttons that are supposed to pop the back stack to certain points either will not function at all or perform an incorrect pop location.
UPDATE: After implementing my solution below, I have solved most issues, except if I start to use the application within the first 2 seconds (about) then I still end up with the random back stack locations upon popping.
WHAT I HAVE FIGURED OUT SO FAR...
If I comment out the Home Launcher intent-filter
and use a BOOT_COMPLETED
filter to launch the app, then everything functions properly again.
Also, I added log statements to view the back stack entry count throughout the program and followed the same exact pathway through the application when it was running properly and not and the numbers are consistent, yet if I click in the red boxes, the app will add fragments to the back stack that it should not. This leads me to believe that it is not an issue with extra items on the back stack that may also be leaking their views through.
SOLVED EDIT: I added a button that did nothing to the second fragment that was match_parent
in both width and height and when I tried to click through to the previous fragment's ListView
, it did NOT work. It seems as if the background is "clickable" and that the previous fragment is being set as the "background/wallpaper"(?).
QUESTIONS
ANSWERED 1) What could cause these "layout leaks" from fragment to fragment after a reboot?
PARTIALLY ANSWERED 2) What could cause the back/cancel buttons (popBackStack(...)
) to not function properly after a reboot?
More code available upon request to facilitate a solution.
回答1:
QUESTION 1: Since it seems that the layout was not being completely removed I decided to try removing all the listeners to all the child items in each fragment's onDestroy
. I ended up finding the method removeAllViewsInLayout()
and decided to try the following code:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
container.removeAllViewsInLayout();
return inflater.inflate(R.layout.welcome_select_cabinet, container, false);
}
This went into each fragment so that before the layout was inflated for that layout the ViewGroup's child items would be cleared. This solved the issue of the "clicking through" to the previous fragment's items.
QUESTION 2: I have added the following immediately after setContentView()
in my "Main" activity:
getFragmentManager().popBackStack();
And then when I add the first fragment in the onCreate
of "Main", I changed the following:
Welcome welcomeFragment = new Welcome();
getFragmentManager().beginTransaction().add(R.id.parent_container, welcomeFragment, "welcomeSelect").commit();
to this:
WelcomeSelectCabinet welcomeSelection = new WelcomeSelectCabinet();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.parent_container, welcomeSelection, "welcomeSelect");
transaction.addToBackStack(null);
transaction.commit();
Now if I wait for about 2 seconds after a reboot, and then start to use the app, I will not encounter any errors. But if I use the app immediately then there are the same errors as before until I reboot again and wait for 2 seconds.
EDIT: I added a 5 second load screen in order to account for the ~2 second "loading" and that seems to have fixed the problem on the Nexus 7 but not the Galaxy Tab 2. I changed the 5 seconds to 10 seconds since the Galaxy Tab 2 seems to take about twice as long to boot and this seemed to have fixed the problem.
EDIT: To make loading more compatible, I was able to tie it into the BOOT_COMPLETED
receiver and set a Boolean that is stored in SharedPreferences
that will determine which fragments to load based on the value, which is reset on the SHUTDOWN
BroadcastReceiver.
来源:https://stackoverflow.com/questions/17372781/home-launcher-issue-with-fragments-after-reboot