没有打开应用程序一段时间后按下按钮时,Android应用程序崩溃?
问题描述:
我正在制作一个应用程序,如果我通常使用它,它可以正常工作,没有崩溃。有两个交换片段的活动,其中一个有两个按钮。如果该应用程序未使用一段时间(小时)并重新打开该应用程序,则如果我按下其中一个按钮,应用程序将崩溃。这只会发生,如果我退出应用程序的主页按钮,如果我退出按Back几次然后这个问题不会发生。没有打开应用程序一段时间后按下按钮时,Android应用程序崩溃?
我也可以复制这个崩溃,如果我打开应用程序,按主页按钮返回到Android主屏幕,然后按我的高级任务杀手应用程序按钮。当我再次打开应用程序时,它打开它留下的相同片段(这很奇怪,我认为在使用任务杀手之后它会重新开始),并且如果我按下其中一个按钮,应用程序崩溃。
编辑:我发现通过它传递我tempmainfrag为空,当我恢复在下面的代码)的应用程序,这两个saveButtonClicked()和deleteButtonClicked(成为一个问题的logcat:
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.fragments;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TimePicker;
import android.widget.Toast;
public class MainActivity extends FragmentActivity
implements MainListFragment.OnListSelectedListener {
MainListFragment tempmainfrag;
InfoFragment infofrag;
int mainPosition = -1;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlayout);
// Check whether the activity is using the layout version with
// the fragment_container FrameLayout. If so, we must add the first fragment
if (findViewById(R.id.fragment_container) != null) { //meaning, if using phone version
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create an instance of MainListFragment
tempmainfrag = new MainListFragment(); //made a context parameter to pass the context
// In case this activity was started with special instructions from an Intent,
// pass the Intent's extras to the fragment as arguments
tempmainfrag.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, tempmainfrag).commit();
Log.i("mydebug","TEMPMAINFRAG: " + tempmainfrag);
}
}
public void onResume()
{
super.onResume();
}
public void onItemSelected(int position, String schedulename, String[] ampm, boolean[] days, int[] times, boolean vibrate) {
// The user selected a list item
//////////////////////////////TWO PANE LAYOUT STUFF///////////////////////////////////
// Capture the article fragment from the activity layout
// InfoFragment articleFrag = (InfoFragment)
// getSupportFragmentManager().findFragmentById(R.id.article_fragment); //article_fragment exists in layout-large
//
// if (articleFrag != null) {
// // If article frag is available, we're in two-pane layout...
//
// // Call a method in the ArticleFragment to update its content
// articleFrag.updateArticleView(position);
//
// } else {
// phone layout - swap frags
mainPosition = position;
// Create fragment and give it an argument for the selected article
infofrag = new InfoFragment();
Bundle args = new Bundle();
args.putInt(infofrag.ARG_POSITION, position);
//new stuff to add info
args.putString(infofrag.ARG_NAME, schedulename);
args.putBooleanArray(infofrag.ARG_DAYS, days);
args.putIntArray(infofrag.ARG_TIMES, times);
args.putBoolean(infofrag.ARG_VIBRATE, vibrate);
args.putStringArray(infofrag.ARG_AMPM, ampm);
infofrag.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, infofrag);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
public void saveButtonClicked(View view) { //pass the click to the mainlistfragment
Log.i("mydebug","TEMPMAINFRAG: " + tempmainfrag);
Log.i("mydebug","enter2222!!!!!!");
boolean redo = false;
//create toast
Toast toast;
//get title
EditText titletext = (EditText)this.findViewById(R.id.titletext);
//get checkboxes
CheckBox check1 = (CheckBox)this.findViewById(R.id.monbox); //recreate checkboxes from view in activity (doesnt extend Activity
CheckBox check2 = (CheckBox)this.findViewById(R.id.tuebox); //so use getActivity())
CheckBox check3 = (CheckBox)this.findViewById(R.id.wedbox);
CheckBox check4 = (CheckBox)this.findViewById(R.id.thubox);
CheckBox check5 = (CheckBox)this.findViewById(R.id.fribox);
CheckBox check6 = (CheckBox)this.findViewById(R.id.satbox);
CheckBox check7 = (CheckBox)this.findViewById(R.id.sunbox);
CheckBox vibratebox = (CheckBox)this.findViewById(R.id.vibratecheckbox);
//get times
TimePicker startpicker = (TimePicker)this.findViewById(R.id.starttimepicker);
TimePicker stoppicker = (TimePicker)this.findViewById(R.id.stoptimepicker);
EditText temppp = titletext;
//check for input errors
if(titletext.getText().toString().length() == 0) //if title is empty
{
redo = true;
toast = Toast.makeText(view.getContext(), "Enter an event name", 4);
toast.show();
//some sick-ass shake animations!!!
Animation shake = AnimationUtils.loadAnimation(titletext.getContext(), R.anim.shake_big);
this.findViewById(R.id.titletext).startAnimation(shake);
}
else if((!check1.isChecked()) && (!check2.isChecked()) && (!check3.isChecked()) &&
(!check4.isChecked()) && (!check5.isChecked()) && (!check6.isChecked()) &&
(!check7.isChecked())) //if all checkboxes arent checked
{
redo = true;
toast = Toast.makeText(view.getContext(), "At least one day of week must be checked", 4);
toast.show();
//more sick-ass shake animations!!!
Animation shake = AnimationUtils.loadAnimation(titletext.getContext(), R.anim.shake_small);
this.findViewById(R.id.checkboxes).startAnimation(shake);
this.findViewById(R.id.daysofweek).startAnimation(shake);
this.findViewById(R.id.frequencytext).startAnimation(shake);
}
if(!redo) //if all info is fine
{
//check to see if time goes into next day
if((startpicker.getCurrentHour() > stoppicker.getCurrentHour())||
((startpicker.getCurrentHour() == stoppicker.getCurrentHour())
&& (startpicker.getCurrentMinute() >= stoppicker.getCurrentMinute())))
{
toast = Toast.makeText(view.getContext(), "Note: Stop time is earlier than start time, so this schedule stops at next day", Toast.LENGTH_LONG);
toast.show();
}
toast = Toast.makeText(view.getContext(), "Schedule saved", Toast.LENGTH_LONG);
toast.show();
//changing old schedule to new one
boolean[] tempdays = {check1.isChecked(), check2.isChecked(), check3.isChecked(), check4.isChecked(),
check5.isChecked(), check6.isChecked(), check7.isChecked()};
tempmainfrag.mainObjectList.changeSchedule(mainPosition, titletext.getText().toString(), tempdays, vibratebox.isChecked(),
startpicker.getCurrentHour()-1, startpicker.getCurrentMinute(), stoppicker.getCurrentHour()-1, stoppicker.getCurrentMinute());
//used to hide keyboard in case its still open when displaying list
InputMethodManager imm = (InputMethodManager)this.getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(titletext.getWindowToken(), 0);
this.onBackPressed(); //replicates backpress to go back to list
}
}
public void deleteButtonClicked(View view)
{
//make a notification
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Delete?");
builder.setIcon(R.drawable.trash_icon);
builder.setMessage("Are you sure you wish to delete this schedule?")
.setCancelable(false)
.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
tempmainfrag.mainObjectList.removeSchedule(mainPosition);
tempmainfrag.exit();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
public void hideKeyboard() //hides keyboard, called whenever reverting back to list
{
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
}
}
我在onResume中尝试了一些解决方案,但想不出任何想法?非常感谢你们。
答
我同意@andr的意思,你可能有一些静态变量,在任务kill之后变量变为空或空,因此如果你试图调用这些变量,你将面临一些错误。我认为这是事实,我可能是错误的,但这取决于你在LogCat中拥有什么。
如果我试图用高级任务杀手退出它,我的应用程序也崩溃了。原因是因为我使用了一些静态变量,在任务结束后变成空的“”。为了避免应用程序崩溃,在我实现类似这样的每个活动中。
希望这可以帮助你。或者您可以提供LogCat或更多信息,以便其他人可以帮助您。
public void onCreate(Bundle savedInstance){
super.onCreate(savedInstance);
//check whether global/static variables are empty or not
//retrieve back the variables or intent it back to other activity
if(globalvariables.UserName.equals(""){
//execute something to deal with it
}
}
任务杀手应用程序是胡扯。不要使用它们。 – 2013-02-21 23:17:06
在崩溃时打印到LogCat的内容是什么?当“活动”进入后台时,Android可能会将其销毁。我的赌注是你有'静态'变量,在重新创建活动后有不正确的值,或者你可以依赖某些在活动生命周期中不能保存和重新创建的值。编辑您的问题并附上崩溃的LogCat输出。此外,发布活动代码*永远不会*伤害,但可以帮助访问者(有时*很多*)更快的诊断。 – andr 2013-02-21 23:21:06