0

mainアクティビティがstartActivityForResultを使用して3つの他のアクティビティを呼び出すゲームを持っています - 最初(SignInActivity)はユーザー名を返します。 (LevelChooser)はgetSharedPreferencesを使用して、そのユーザーの名前で環境設定ファイルを検索したり、新しいものを作成したり、これまでのユーザーの進捗状況(レベルはロックされていない、稼いだ星)を表示し、 3番目のファイル(GameActivity)は、レベルが正常に完了した場合にユーザーの設定ファイルを更新してからmainを経由してLevelChooserに戻ります。 LevelChooserでは、SignInActivityに戻るためにonBackPressedをオーバーライドしました。 GameActivityにはonFinishがオーバーライドされていますので、どうなるかにかかわらずLevelChooserに戻ります。Android getSharedPreferences startActivityForResult間欠エラー

これは10回中9回が意図したとおりに動作しますが、時には実際の星とレベルを表示する代わりに、LevelChooserは一連の誤った理論上不可能な値を示します1つのレベルはロックされているように示されていますが、3つ星で完成しています)。これはしばしば(ただし必ずしもそうではありませんが)レベルを選択して最初にゲームを開いたときに元のレベルに戻った場合に発生します。ロックされていないレベルを再生できるようになりますが、完了すればGameActivityあなたがLevelChooserに戻ったときに、レベルと同じ間違ったレベルが表示されます。または、LevelChooserから戻って同じユーザー名を再度選択すると、期待どおりの動作に戻ります。また、レベルを繰り返し開始してエラーを再現することもできました。十分な時間をおいてからは、最終的には間違ってしまいます。自分のユーザー名(と私はと思う、すべてのユーザーのためにと考える)間違った情報は常に同じです。つまり、問題は断続的ですが、発生するとランダムではありません。

私はデバッグを試しましたが、何らかの理由で(a)エミュレータではなく電話機で問題が発生していました。(b)電話機でデバッグしているときそうでない場合は、間違ったレベルの画面を表示するのではなく、単に「Xが停止していない」AFAIRダイアログを終了するだけです。私がデバッグで見ることができた唯一のことは、LevelChooserアクティビティのonCreateが複数回実行されることがあることです。

問題が断続的で再現性がないため、非同期処理がタイムリーかつリニアな方法で完了していると思われることがありましたか、通常は必ずしもそうではありません。そうでなければ、私はActivityライフサイクルに関連して重要な何かを理解できなかったと思っています。そうでなければ、私は困惑し、推測しています。

main Activity

public class MainActivity extends AppCompatActivity { 

public ImageView splash; 
private int GET_USER_NAME_CODE = 0; 
private int GET_LEVEL_CODE = 1; 
private int PLAY_GAME_CODE = 2; 
private String user; 
private int level; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    // remove title 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    setContentView(R.layout.activity_splash_screen); 

    splash = (ImageView) findViewById(R.id.splashView); 

    splash.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      Intent sign_intent = new Intent(MainActivity.this, SignInActivity.class); 
      startActivityForResult(sign_intent, GET_USER_NAME_CODE); 
     } 
    }); 

} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{ 
    super.onActivityResult(requestCode, resultCode, data); 
    // check if the request code is same as what is passed 
    if(requestCode==GET_USER_NAME_CODE) 
    { 
     user=data.getStringExtra("USER"); 
     Intent intent = new Intent(MainActivity.this, LevelChooser.class); 
       intent.putExtra("user", user); 
       startActivityForResult(intent, GET_LEVEL_CODE); 
    } 
    else { 
     if(requestCode==GET_LEVEL_CODE) { 
      level=data.getIntExtra("LEVEL", 0); 
      if(level==-1) { 
       Intent sign_intent = new Intent(MainActivity.this, SignInActivity.class); 
       startActivityForResult(sign_intent, GET_USER_NAME_CODE); 
      } 
      else { 
       Intent intent = new Intent(MainActivity.this, GameActivity.class); 
       intent.putExtra("user", user); 
       intent.putExtra("level", level); 
       startActivityForResult(intent, PLAY_GAME_CODE); 
      } 
     } 
     else { 
      if(requestCode==PLAY_GAME_CODE) { 
       user=data.getStringExtra("user"); 
       Intent intent = new Intent(MainActivity.this, LevelChooser.class); 
       intent.putExtra("user", user); 
       startActivityForResult(intent, GET_LEVEL_CODE); 
      } 
     } 
    } 
} 

LevelChooser

public class LevelChooser extends AppCompatActivity { 

private String user; 
private ImageView[] level; 
private Boolean[] locked; 
private int[] stars; 
private SharedPreferences userprefs; 
private SharedPreferences.Editor prefseditor; 
private Boolean createNewPrefsFile = false; 
private int tempResIdVisible; 
private int tempResIdInvisible; 
private ImageView tempView; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    setContentView(R.layout.levelchooser); 
} 

@Override 
protected void onStart() { 
    super.onStart(); 


     level = new ImageView[21]; 
     locked = new Boolean[21]; 
     stars = new int[21]; 

     user = getIntent().getStringExtra("user"); 
     userprefs = getSharedPreferences(user, MODE_PRIVATE); 
     prefseditor = userprefs.edit(); 

     //level numbers for views etc start from 1 to match images etc 
     level[0] = null; 
     locked[0] = null; 
     stars[0] = 0; 

     locked[1] = false; 
     level[1] = (ImageView) findViewById(R.id.level1); 
     level[1].setOnClickListener(new LevelClickListener(level[1], 1)); 
     if (!userprefs.contains("stars1")) { 
      createNewPrefsFile = true; 
     } 
     stars[1] = userprefs.getInt("stars1", 0); 
     if (stars[1] != 0) { 
      for (int j = 1; j < 4; j++) { 
       tempResIdInvisible = getResources().getIdentifier("stars" + j + "_1", "id", getPackageName()); 
       tempView = (ImageView) findViewById(tempResIdInvisible); 
       tempView.setVisibility(View.INVISIBLE); 
      } 
      tempResIdVisible = getResources().getIdentifier("stars" + stars[1] + "_1", "id", getPackageName()); 
      tempView = (ImageView) findViewById(tempResIdVisible); 
      tempView.setVisibility(View.VISIBLE); 
     } 

     for (int i = 2; i < 21; i++) { 
      locked[i] = userprefs.getBoolean("locked" + i, true); 
      if (locked[i]) { 
       tempResIdVisible = getResources().getIdentifier("padlock" + i, "id", getPackageName()); 
       tempResIdInvisible = getResources().getIdentifier("level" + i, "id", getPackageName()); 
      } else { 
       tempResIdVisible = getResources().getIdentifier("level" + i, "id", getPackageName()); 
       tempResIdInvisible = getResources().getIdentifier("padlock" + i, "id", getPackageName()); 
       level[i] = (ImageView) findViewById(tempResIdVisible); 
       level[i].setOnClickListener(new LevelClickListener(level[i], i)); 
      } 
      tempView = (ImageView) findViewById(tempResIdVisible); 
      tempView.setVisibility(View.VISIBLE); 
      tempView = (ImageView) findViewById(tempResIdInvisible); 
      tempView.setVisibility(View.INVISIBLE); 

      stars[i] = userprefs.getInt("stars" + i, 0); 
      if (stars[i] != 0) { 
       for (int j = 1; j < 4; j++) { 
        tempResIdInvisible = getResources().getIdentifier("stars" + j + "_" + i, "id", getPackageName()); 
        tempView = (ImageView) findViewById(tempResIdInvisible); 
        tempView.setVisibility(View.INVISIBLE); 
       } 
       tempResIdVisible = getResources().getIdentifier("stars" + stars[i] + "_" + i, "id", getPackageName()); 
       tempView = (ImageView) findViewById(tempResIdVisible); 
       tempView.setVisibility(View.VISIBLE); 
      } 
     } 

     if (createNewPrefsFile) { 
      for (int i = 1; i < 21; i++) { 
       prefseditor.putBoolean("locked" + i, locked[i]); 
       prefseditor.putInt("stars" + i, stars[i]); 
       prefseditor.commit(); 
      } 
     } 
} 

GameActivity

public class GameActivity extends AppCompatActivity implements TextToSpeech.OnInitListener { 

//TTS Object 
private TextToSpeech myTTS; 
//TTS status check code 
private int MY_DATA_CHECK_CODE = 0; 
private int level; 
private String user; 
private PhonemeGroup levelGroup; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 

    level = getIntent().getIntExtra("level", 0); 
    user = getIntent().getStringExtra("user"); 
    levelGroup = initializeLevels(level); 

    Intent checkTTSIntent = new Intent(); 
    checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); 
    startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE); 
} 

@Override 
public void finish() { 
    Intent intent = new Intent(); 
    intent.putExtra("user", user); 
    setResult(2, intent); 

    super.finish(); 
} 

@Override 
public void onStop() { 
    if (myTTS != null) { 
     myTTS.stop(); 
    } 
    super.onStop(); 
} 

@Override 
public void onDestroy() { 
    if (myTTS != null) { 
     myTTS.shutdown(); 
    } 
    Button ok_button = (Button) findViewById(R.id.button); 
    ok_button.setOnClickListener(null); 
    ImageView tickImageView = (ImageView) findViewById(R.id.tickImageView); 
    tickImageView.setOnClickListener(null); 
    ImageView starsView = (ImageView) findViewById(R.id.starsImageView); 
    starsView.setOnClickListener(null); 

    super.onDestroy(); 

    unbindDrawables(findViewById(R.id.GameParentView)); 
    System.gc(); 
} 

正しい表示のスクリーンショット:A screenshot of LevelChooser with no errors

上のレベル1を選択して、バックアウト後

スクリーンショット:Screenshot of LevelChooser with errors

答えて

0

それが問題のようなgetSharedPreferences()ではないことが判明したのではなく、getIntent().getStringExtra()によって返される変数userが時々あったこと - の状況下で、私は、ハードを発見しました確実にピンダウンまたは再現 - nullthis questionのように。その文字列はgetSharedPreferences()のパラメータとして使用され、結果としてユーザnullの保存結果が保存されました。これらの結果(問題の2番目のイメージに表示)は、問題が再発するたびに表示されます。

ソリューション - getStringExtra()nullを返す必要がありますなぜそれがまだ説明されていませんが - に有効なユーザーを必要と活動の両方のonCreateに次のコードを入れて余分にヌルガードた:

if(getIntent().getExtras()==null || getIntent().getStringExtra("user")==null) { 
    Intent intent = new Intent(); 
    setResult(0, intent); 
    finish(); 
    } 

新しいアクティビティのレイアウトが読み込まれる前にこれを実行すると、メインアクティビティに戻り、ユーザーに問題が発生することなく再試行されます。

関連する問題