2013-02-21 19 views
0

Я делаю приложение, и если я его использую, он нормально работает без сбоев. Существует одно действие с двумя фрагментами, которые обмениваются, и на нем есть две кнопки. Если приложение не используется какое-то время (часы), и приложение снова открывается, то, если я нажму одну из кнопок, приложение выйдет из строя. Это происходит только в том случае, если я выйду из приложения с кнопкой «Домой», если я выйду из него, нажав «Назад» несколько раз, эта проблема не возникает.Сбой приложения для Android при нажатии кнопки после того, как приложение не открыто какое-то время?

Я также могу воспроизвести этот сбой, если я открою приложение, нажмите кнопку home, чтобы вернуться на главный экран Android, и нажмите кнопку приложения Advanced Task Killer. Когда я снова открою приложение, он открывается на том же фрагменте, на котором он остановился (что странно, я подумал, что после использования убийцы задачи он начнет работать свежий), и если я нажму одну из кнопок, приложение выйдет из строя.

EDIT: я узнал через LogCat, что проходящий мой tempmainfrag утратившие когда я возвращаюсь приложение в следующем коде, который становится проблемой как в saveButtonClicked() и deleteButtonClicked():

/* 
* 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, но не могу придумать ничего, никаких идей? Спасибо, ребята, много.

+0

Приложение для убийц задач - это крэпс. Не используйте их. – 2013-02-21 23:17:06

+1

Что печатается в LogCat при сбое? когда «Активность» переходит на фон, Android может его уничтожить. моя ставка заключается в том, что у вас есть переменные 'static', которые после воссоздания активности имеют неправильные значения или, альтернативно, вы полагаетесь на некоторое значение, которое не сохраняется и воссоздается в течение жизненного цикла активности. отредактируйте свой вопрос и приложите вывод журнала LogCat об аварии. также, проводя код активности * никогда * болит, но может помочь посетителям в (иногда * много *) более быстрой диагностике. – andr

ответ

0

Я согласился с @andr, что у вас могут быть некоторые статические переменные, и после того, как задача уничтожила переменные, они стали пустыми или нулевыми, поэтому вы столкнетесь с некоторой ошибкой, если попытаетесь вызвать переменные. Я предположил, что это так, и я могу ошибаться, хотя это зависит от того, что у вас есть в вашем LogCat.

Мое приложение также срабатывает, если я попытался выйти из него с помощью расширенной задачи killer. Причина в том, что я использовал некоторые статические переменные, которые оказались пустыми »после того, как задача была убита. Чтобы избежать краха приложения, в каждом действии я реализовал что-то вроде этого.

Надеюсь, это вам поможет. Или вы можете предоставить 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 
     } 
} 
Смежные вопросы