2013-10-27 3 views
13

는 최근 다음과 같습니다 데모 응용 프로그램을 만든 조각을 사용하기 시작했다 :조각의 동일한 인스턴스를 저장하고 재사용하는 방법은 무엇입니까?

조각 1 사이의 각 버튼 스위치에

Demo App

클릭, 조각 2, 조각 3. 내가 무엇

달성을 시도하는 것은 각 단편의 인스턴스를 1 개만 가지고 재사용하는 것입니다. (모든 단편은 동적으로 작성되고 추가됩니다. 현재 나는 프래그먼트의 HashMap을 생성하고 각 인스턴스를 배치하고 거기에서 그것을 잡아서이 작업을 수행하고 있습니다.

내 질문은 : 더 좋은 방법이 있나요 : FragmentManager의 putFragment (...) 메서드를 사용하여? putFragment (Bundle bundle, String key, Fragment fragment) 내 경우에 어떻게 사용하는지 알아낼 수 없습니다. 누구든지이 방법을 사용하는 방법에 대한 예를 들어 줄 수 있다면.

내 활동에서 각 조각에 대한 참조를 보유하는 것이 비용이 많이 듭니까? 이것은 모든 조각들을 살아있게합니까? 이 문제를 해결하기 위해 소프트 참조를 사용하고 있지만 이것이 올바른 방법인지 확실하지 않습니다. 이 작업을 수행하는 가장 좋은 방법인지 알고 싶다면이 작업을 수행 할 다른 방법을 알려주십시오.

미리 감사드립니다.

UPDATE : 나는 그것이 다시 스택에 존재하지 않는 경우에만 추가하려고, 다시 스택에서 조각을 다시 사용하려고

여기 내 코드입니다.

10-28 13:21:40.255: ERROR/MessageQueue-JNI(3548): java.lang.IllegalStateException: Fragment already added: FragmentOne{423db570 #0 id=0x7f050006 fragOne} 

public class MainActivity extends Activity implements View.OnClickListener { 

private Button btnOne; 
private Button btnTwo; 
private Button btnThree; 

/* Called when the activity is first created. 
    */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    initialize(); 
    if(findViewById(R.id.fl) != null){ 
     if(savedInstanceState != null) 
      return; 
    } 

    FragmentManager.enableDebugLogging(true); 
    updateView("fragOne"); 
} 

private void initialize(){ 
    btnOne = (Button) findViewById(R.id.button1); 
    btnTwo = (Button) findViewById(R.id.button2); 
    btnThree = (Button) findViewById(R.id.button3); 
    btnOne.setOnClickListener(this); 
    btnTwo.setOnClickListener(this); 
    btnThree.setOnClickListener(this); 
    fragHolder = new HashMap<String, SoftReference<Fragment>>(); 
} 

private void updateView(String tag){ 
    FragmentTransaction ft = getFragmentManager().beginTransaction(); 
    Fragment frag = getFragmentManager().findFragmentByTag(tag); 

    boolean addToStack = true; 
    if(frag == null){ 
     if(tag.equals("fragOne")) 
      frag = new FragmentOne();  
     else if(tag.equals("fragTwo")) 
      frag = new FragmentTwo(); 
     else if(tag.equals("fragThree")) 
      frag = new FragmentThree(); 
    }else{ 
     //Don't add to back stack 
     addToStack = false; 
    } 
    ft.replace(R.id.fl, frag, tag); 
    if(addToStack) 
     ft.addToBackStack(null); 
    ft.commit(); 
} 

    @Override 
    public void onClick(View v) { 
     switch(v.getId()){ 
      case R.id.button1: 
       updateView("fragOne"); 
       break; 
      case R.id.button2: 
       updateView("fragTwo"); 
       break; 
      case R.id.button3: 
       updateView("fragThree"); 
       break; 
     } 
    } 
} 
+0

FragmentTransactions를 살펴 보았습니까? 그들은 당신에게 도움이 될 수 있습니다. –

답변

2

은 다음 샘플에 도움이 될 수하는 FragmentTransaction을 보여하려면 다음> 다음 버튼을 다시 누르려고 -> 다시 와서 그것을에 - 나는 한 조각에서 멀리 이동 한 후 아래의 코드는 나에게 불법 상태 예외를 제공합니다 당신.

먼저 활동의 onCreate()에서 초기화 작업을하고 싶습니다.하지만 몇 가지 사항을 변경해 보겠습니다.

public class MainActivity extends Activity implements View.OnClickListener { 

private Button btnOne; 
private Button btnTwo; 
private Button btnThree; 

/* Called when the activity is first created.*/ 
@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    initialize(); 
    if(findViewById(R.id.fl) != null) 
    { 
     if(savedInstanceState != null) 
     { 
      FragmentTransaction trans = getFragmentManager().beginTransaction(); 

      //This is where we add our first fragment 
      trans.add(R.id.fl, new FragmentOne()); 
      trans.commit(); 
     } 
    } 
} 

private void initialize() 
{ 
    btnOne = (Button) findViewById(R.id.button1); 
    btnTwo = (Button) findViewById(R.id.button2); 
    btnThree = (Button) findViewById(R.id.button3); 
    btnOne.setOnClickListener(this); 
    btnTwo.setOnClickListener(this); 
    btnThree.setOnClickListener(this); 
} 

public void onClick(View view) 
{ 
    //Here is where we'll actually transfer the fragments 

    FragmentTransaction trans = getFragmentManager().beginTransaction(); 
    switch(v.getId()){ 
     case R.id.button1: 
      trans.replace(R.id.fl, new FragmentOne()); 
      trans.addToBackStack(null); 
      trans.commit(); 
      break; 
     case R.id.button2: 
      trans.replace(R.id.fl, new FragmentTwo()); 
      trans.addToBackStack(null); 
      trans.commit(); 
      break; 
     case R.id.button3: 
      trans.replace(R.id.fl, new FragmentThree()); 
      trans.addToBackStack(null); 
      trans.commit(); 
      break; 
    } 
} 

이렇게하면 하나의 조각에서 다른 조각으로 쉽게 전환 할 수 있습니다.

+0

답변 해 주셔서 감사합니다. 처음에는이 접근법을 시도했지만 모든 트랜잭션을 백 스택에 추가하여 모든 트랜잭션의 크기를 계속 증가 시켰습니다. 기억은 내 실제 애플 리케이션에 문제가 있다고 언급했듯이. 그래서 나는 다시 스택의 엔트리 수를 제한하고 싶다. 더 좋은 질문이 될 것입니다 : FIFO 큐로 백 스택을 사용할 수 있다면 -> 10 트랜잭션이 11을 추가 할 때 1을 버린 후에>. – Naveed

+1

당신은'disallowAddToBackStack()'을 호출 할 수 있고 정적 스택이나 너무 많은 것들이 백 스택에있을 때 정적 인 것들을 추적 할 수 있습니다. –

+0

나는 또한 내가 얻었던 불법적 인 상태 예외를 해결했다. 이미 동일한 조각을 추가하지 않으려 고 노력할 필요가 있습니다. – Naveed

1

FragmentManager는 자체 메모리 관리를 수행합니다. 논리에 따라 인스턴스를 중지/재 작성하거나 인스턴스에 유지합니다. onSaveInstanceState()

또는 프래그먼트에서 setRetainInstance(true)을 사용하여 시스템이 인스턴스를 활성 상태로 유지하도록 할 수 있습니다.

이렇게하면 트랜잭션을 만드는 방법입니다.

FragmentTransaction fragmentTransaction = context.getSupportFragmentManager().beginTransaction(); 
    fragmentTransaction.replace(R.id.layout, new MyFragment(), f.getClass().getName()); 
    fragmentTransaction.commit(); 
+1

답변 해 주셔서 감사합니다. 이전에이 방법을 시도해 보았습니다. 단 하나의 차이점은 조각 하나에 무언가를 입력 한 다음 조각 2로 바꾸면 다시 탐색 할 때 조각 1의 새 인스턴스를 작성하면 재사용 할 수있는 변경 사항이 느슨해집니다. 같은 인스턴스 (텍스트가 여전히 존재하는 경우) – Naveed

관련 문제