2016-09-16 54 views
0

我有一個用XML中描述的片段定義的活動。在活動,我檢索對片段的引用:在XML中定義的Android片段是不同於其父級活動內部片段的實例

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

    FragmentManager manager = getSupportFragmentManager(); 
    mFragment = (DetailActivityFragment) manager.findFragmentById(R.id.fragment); 
    ... 
} 

我所說的片段的(自定義)updateUI()方法,它具有不同的ID比活性:

DetailActivity: tbm 440; got fragment: (0x038c6009) (invisible) 
DetailActivityFragment: tbm 162; fragment: (0x05f54af9) updating UI 

然後,當片段被破壞:

DetailActivityFragment: tbm 131; destroying fragment (0x038c6009) 

即是活性內部產生相同的片段,以及不同實際片段。

在如此重要的情況下,這裏就是我的日誌片段的ID:

Log.d(TAG, String.format("tbm 162; (0x%08x) updating UI", System.identityHashCode(this)); 

此外,在「TBM 162」日誌報表所顯示的ID始終是相同的,並且總是第一個的ID相符片段被實例化的時間。

這種變態有什麼特別的原因嗎?片段的im-memory ID如何在實例化的時間與片段在其內部引用的時間之間發生變化?當然,問題在於,在updateUI方法中,引用了UI元素,這些UI元素包含在(現在隱藏並分離的)原始片段中,因此UI永遠不會真正改變。

TIA!

編輯:

的updateUI()方法只是顯示一些領域,所以我不認爲這是相關的,但在要求的情況下,我失去了一些東西:

public void updateUi(final InformativeBean bean) { 
    Log.d(TAG, String.format("tbm 162; (0x%08x) (%s) updating UI", 
          System.identityHashCode(this), 
          this)); 

    if (mView == null || bean == null) { 
     return; 
    } 

    if (bean.getBattery() != null) { 
     TextView battery_info = (TextView) mView.findViewById(R.id.battery_field); 
     battery_info.setText(String.format("%s%%", bean.getBattery().getPercentage())); 
    } 

    ImageView burnin_view = (ImageView) mView.findViewById(R.id.burnin_flag_image); 
    if (bean.isBurninComplete()) { 
     burnin_view.setImageResource(R.drawable.ic_flag_burnin_complete); 

    } else { 
     burnin_view.setImageResource(R.drawable.ic_flag_burnin_incomplete); 

    } 

    Program program = bean.getProgram(); 
    Program new_program = bean.getPendingProgram(); 

    TextView current_program_view = (TextView) mView.findViewById(R.id.current_program_field); 
    current_program_view.setBackgroundColor(mTransparentColor); 

    if (new_program == null) { 
     if (program == null) { 
      return; 
     } 

     current_program_view.setText(program.toString()); 

    } else if (program == null || program.equals(new_program)) { 
     current_program_view.setText(new_program.toString()); 

    } else { 
     current_program_view.setText(String.format("%s -> %s", program, new_program)); 
     current_program_view.setBackgroundColor(mProgramBackgroundColor); 

    } 

} 

編輯:

即使怪異,片段即使在本身的變化ID:

DetailActivityFragment: tbm 065; (0x06a9e492) (DetailActivityFragment{6a9e492 #0 id=0x7f0d0075}) in attach 
DetailActivityFragment: tbm 104; (0x06a9e492) (DetailActivityFragment{6a9e492 #0 id=0x7f0d0075}) in onCreateView 
DetailActivity: tbm 463; got fragment: (0x06a9e492) (DetailActivityFragment{6a9e492 #0 id=0x7f0d0075}) (invisible) 
DetailActivityFragment: tbm 162; (0x068d3e1a) (DetailActivityFragment{68d3e1a}) updating UI 

因此它在onAttach和onCreateView中是0x06a9e492(並且這是活動接收的引用),但固執地在updateUI中使用0x068d3e1a。

+0

您可以發佈您的自定義updateUI方法? – harshitpthk

回答

0

經過大量調查發現,包含錯誤片段的活動中的某個字段持有對該活動的引用。更改該字段以使其通過當前的活動實例(vs持有對該字段的外部活動的隱式引用)修復了該問題。我仍然有些困惑,即使在「活躍」時,片段的ID可以改變,但至少我可以取得進展。

這幫了很大的忙:http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html。起初我並未發現問題是一種泄漏。

實際上,這是(原件,錯誤的)代碼:

DetailActivity 
    ... 
    some_field = new Listener() { 
     // The outer activity is retained, causing its fragment to be (partially?) re-used. 
     onSomeEvent() { 
      Toast.makeText(DetailActivity.this, "Got Some Event", ...).show(); 
     } 
    }; 
    ... 

和新的工作代碼更像是:

DetailActivity 
    ... 
    some_field = ListenerWithActivity.getInstance(this); 
    ... 

ListenerWithActivity: 

    public static ListenerWithActivity getInstance(Activity activity) { 
     ListenerWithActivity existing = getExisting(); 
     if (existing == null) { 
      existing = new ListenerWithActivity(); 
     } 

     existing.setActivity(activity); 
     return existing; 
    } 

    public void onSomeEvent() { 
     Toast.makeText(getActivity(), "Got Some Event", ...).show(); 
    }