9

したがって、興味深い問題があります。プログラムで新しいフラグメントを追加すると、OnBackStackChangedListenerからonBackStackChangedメソッドが2回呼び出されますが、1回だけ呼び出す必要があります。ここに活動の私のコードは次のとおりです。onBackStackChanged()は、新しいフラグメントがバックスタックに追加されたときに2回呼び出されました。

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 

public class MainActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener{ 

    private FragmentManager fragmentManager; 
    private Button button1; 
    private Button button2; 
    private Button button3; 

    private Fragment defaultFragment; 
    private Fragment previousFragment; 
    private Fragment currentFragment; 
    private String currentFragmentTag; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     button1 = (Button) findViewById(R.id.button); 
     button2 = (Button) findViewById(R.id.button2); 
     button3 = (Button) findViewById(R.id.button3); 

     button1.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       showFragment(new FragmentOne(), FragmentOne.TAG); 
      } 
     }); 

     button2.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       showFragment(new FragmentTwo(), FragmentTwo.TAG); 
      } 
     }); 

     button3.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       showFragment(new FragmentThree(), FragmentThree.TAG); 
      } 
     }); 

     setupFragmentManager(); 

    } 

    private void setupFragmentManager() { 
     fragmentManager = getSupportFragmentManager(); 
     fragmentManager.addOnBackStackChangedListener(this); 


     FragmentOne fragmentOne = new FragmentOne(); 
     defaultFragment = fragmentOne; // fragment for default 

     currentFragmentTag = FragmentOne.TAG; 
     currentFragment = fragmentOne; 

     fragmentManager.beginTransaction() 
       .add(R.id.fragments_container, currentFragment, currentFragmentTag) 
       .addToBackStack(currentFragmentTag) 
       .commit(); 
    } 

    public void showFragment(Fragment fragment, String fragmentTag) { 
     previousFragment = currentFragment; 
     currentFragment = fragment; 
     fragmentManager.beginTransaction() 
       .hide(previousFragment) 
       .add(R.id.fragments_container, fragment, fragmentTag) 
       .addToBackStack(fragmentTag) 
       .commit(); 
    } 

    @Override 
    public void onBackStackChanged() { 
     Log.d("MY_TAG" , "onBackStackChangedListener - " + fragmentManager.getBackStackEntryCount()); 

     if (fragmentManager.getBackStackEntryCount() > 0) {  
      String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); 
      currentFragment = fragmentManager.findFragmentByTag(fragmentTag); 
     } else { 
      currentFragment = defaultFragment; 
     } 

// some code... 
    } 

    @Override 
    public void onBackPressed() { 
     if (fragmentManager.getBackStackEntryCount() == 1) { 
      finish(); 
     } else { 
      super.onBackPressed(); 
     } 
    } 
} 

とフラグメントクラス:

public class FragmentOne extends Fragment { 

    public static final String TAG = FragmentOne.class.getSimpleName(); 

    private Context context; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 


     context = getActivity(); 
     View topLevelView = LayoutInflater.from(context).inflate(R.layout.fragment_layout, container, false); 

     TextView textView = (TextView) topLevelView.findViewById(R.id.fragment_Text); 

     textView.setText("This is FRAGMENT ONE"); 

     return topLevelView; 
    } 

} 

FragmentTwoとFragmentThreeがFragmentOneと同じです。

と私は私のアプリを起動すると、ログに私は以下を参照してください。

onBackStackChangedListener - 1 
onBackStackChangedListener - 1 

ボタン(ショー次のフラグメント)を押した後、私は次を参照してください。

onBackStackChangedListener - 2 
onBackStackChangedListener - 2 

と別の1:

onBackStackChangedListener - 3 
onBackStackChangedListener - 3 

変更後

.add(R.id.fragments_container, currentFragment, currentFragmentTag) 

.replace(R.id.fragments_container, currentFragment, currentFragmentTag) 

にdoesntのは、問題を解決します。

しかし、それは非常に奇妙です。私のOnBackStackChangedListenerが、フラグメントを追加した後に複数回の独自のメソッドを呼び出すのはなぜですか?

+0

何もない本当にあなたの問題をどう行うが、 'あなたはそれぞれに' 'button.setOnClickListener(本)、直接活動に、そしてあなたのボタンごとにView.OnClickListenerインターフェイスを実装することができますし、あなただけのいずれかが必要onClick'メソッドを使用し、クリックステートメントを使用してクリックされたビューを検索し、クリックの振る舞いを必要とするビューがあるたびに定義するのではなく、1つの実装からロジックを実行します。 – mwieczorek

答えて

11

起こる可能性はありません。同様のプロジェクトを作成し、デバッガに分割しました。新しいサポートライブラリのバグです。 bug opened in the trackerがあります。

25.0.0に戻すと、正常に動作します。

compile 'com.android.support:appcompat-v7:25.0.0' 
compile 'com.android.support:support-v4:25.0.0' 

release notesで述べたが、良いしている、問題が25.4.0に固定されていることを、in the issue trackerに記載されていないが。

+0

いいえ、私が行を削除したとき:.hide(previousFragment) - それは問題を解決しません。そして、最初の(デフォルトの)フラグメントを追加するにはhideメソッドはありません。だから、この問題はhideメソッドに依存しません。 –

+0

@AlexD。あなたは大丈夫です。答えを更新しました。 – azizbekian

+0

良いfind @azizbekian –

2

ただ更新。 Googleは最終的にこの問題を修正してバージョン25.4.0をリリースしました。のみ

、今のサポートスタッフが、GoogleのMavenのリポジトリからフェッチされることを意図されています

maven { url 'https://maven.google.com' } 

だから、あなたはすべての新しいバージョンの使用を開始し、SDKマネージャからローカルサポートリポジトリをアンインストールすることができます。

関連する問題