[英]onClickListener not working (properly) after ConfigurationChange in fragments
嗯,這是一個艱難的 。 至少, 我想是這樣......要清理:
在搜索互聯網(使用谷歌)后,我沒有找到任何問題的答案。
我發現的一切都是關於人們為他們的View
錯誤設置onClickListener
的。 我想在我的情況下這是同樣的問題,但沒有其他問題與我的相符。
這似乎是同樣的問題......它沒有答案。
我在AppCompatActivity
設置了三個Fragment
和一個ViewPager
。
viewPager = (ViewPager) findViewById(R.id.main_view_pager);
viewPager.setAdapter(new SectionsPagerAdapter(getSupportFragmentManager()));
由SectionsPagerAdapter
處理。
public class SectionsPagerAdapter extends FragmentPagerAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return MainTextHolder.newInstance(tabIndicatorOnClick);
case 1:
return PostWriter.newInstance(tabIndicatorOnClick);
case 2:
return TopPage.newInstance(tabIndicatorOnClick);
default:
return Error.newInstance();
}
}
@Override
public int getCount() {
return 3;
}
// ... more methods
}
在每個Fragment
我都有一些內容和一個自定義的TabIndicator
。
(以下xml
文件是我的View
for the indicator)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<View
android:id="@+id/fragment_divider_one"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:tag="one" />
<View
android:id="@+id/fragment_divider_two"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:tag="two" />
<View
android:id="@+id/fragment_divider_three"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:tag="three" />
</LinearLayout>
然后我在Fragment
的onCreateView(LayoutInflater inflater, ViewGroup Bundle savedInstanceState)
方法中為每個View
(分隔OnClickListener
設置一個OnClickListener
。 OnClickListener
已經在我的Activity
中准備好了,我還實例化了我的ViewPager
以便我可以更改當前的Item
( Fragment
/ tab)。
private final View.OnClickListener tabIndicatorOnClick = new View.OnClickListener() {
@Override
public void onClick(View view) {
if (view.getTag().toString().equals("one"))
viewPager.setCurrentItem(0, true); // second argument for smooth transition
else if (view.getTag().toString().equals("two"))
viewPager.setCurrentItem(1, true);
else if (view.getTag().toString().equals("three"))
viewPager.setCurrentItem(2, true);
}
};
我通過將OnClickListener
放入我的newInstance(View.OnClickListener tabIndicatorOnClick)
方法將其傳遞給Fragment
。
這是其中一個片段。 對其他人來說是完全相同的!
public static MainTextHolder newInstance(View.OnClickListener tabIndicatorOnClick) {
MainTextHolder fragment = new MainTextHolder();
Bundle args = new Bundle();
fragment.putIndicatorTabIndicatorOnClick(tabIndicatorOnClick);
fragment.setArguments(args);
fragment.setRetainInstance(true);
return fragment;
}
我的putIndicatorTabIndicatorOnClick(View.OnClickListener tabIndicatorOnClick)
方法是一個Interface
的Void
。 它只是將OnClickListener
應用於Class
( Fragment
)。
@Override
public void putIndicatorTabIndicatorOnClick(View.OnClickListener tabIndicatorOnClick) {
this.tabIndicatorOnClick = tabIndicatorOnClick;
}
是的確如此 。 它工作得很好......直到ConfigurationChange
發生。 在我的情況下,我通過改變方向測試它。
在ConfigurationChange
之后會發生一切正常的事情。 OnClickListener
應用於所有 Fragment
的所有 View
, 但 tabIndicatorOnClick
OnClickListener
是第二個和第三個Fragment
中的空對象引用 。
因此,在PostWriter和首頁上 ,竟然沒有一個真正的OnClickListener
上View
的對什么都原因。 但它變得更好:在MainTextHolder
Fragment
, tabIndicatorOnClick
不是null object reference
,但它不再更改ViewPager
的Item
。 它運行代碼,但不會滾動Tab
。
當打開“不要保持活動”而不是設備的開發者選項並離開應用程序時,所有OnClickListener
都是null object references
。 甚至是MainTextHolder
那些。
在ConfigurationChange
之后, OnClickListener
被傳遞到我的第一個Fragment
,但是它沒有正常工作,並且在剩下的Fragment
它甚至沒有傳遞/ null object reference
。
可以通過銷毀Activity
然后重新加載來復制該問題。
......我不知道出了什么問題。 我希望我能正確地構建我的問題。
minSdkVersion : 14
targetSdkVersion : 25
我的ViewPager上已經有一個ViewPager
。 這沒有OnClickListener
所以我添加了自己的“重疊”指標,它們具有所需的OnClick
功能。 我也喜歡它的外觀,但如果你能為我的TabIndicator
提供更好的解決方案,我也很樂意將它作為答案。
我遇到了將方法多次放入xml
:onClick
屬性的解決方案,但為此,我需要為每個Fragment
創建相同的OnClickListener
,這不是很好的方式,它也沒有解決我的問題,但是繞過它。 - 我需要將ViewPager
傳遞給我的Fragment
,然后從xml
調用該方法,正如我所說,這只是另一種方式,而不是我喜歡的方式。 我也不知道它是否有效。 我很可能會測試它。
Fragment
中的其他OnClickListener
仍能正常工作。 所以正如我所說,問題在於OnClickListener
本身不能正常工作/是一個null object reference
。
首先,為編寫問題的詳細描述做得很好。 StackOverflow上的許多提問者都可以從這個問題的能力中學習表達問題。
這個錯誤似乎來自於不考慮Fragment生命周期的變化。 在ViewPager中,Fragments將通過各種狀態,包括隱藏和顯示在臨時屏幕外時,如果它們在屏幕外並且系統釋放內存,則暫停和恢復,如果Android系統決定保存實例狀態,則最終創建和銷毀您的活動(例如來自配置更改)。 在后一種情況下,Android將嘗試從ViewPager中保存的實例狀態恢復Fragments的狀態。 由於您的Fragments無法保存View.OnClickedListener
因此它們在參數中傳遞,它們在恢復時最終會返回一個null
指針,這會導致您的錯誤。
要修復錯誤,我建議您不要將View.OnClickedListener
作為參數傳遞給Fragments。 相反,通過Activity中的公共方法將OnClickListener
暴露給OnClickListener
,讓Fragments在onResume()
中自己獲取它。 這樣,您可以保證Fragments在處於恢復狀態時將具有對View.OnClickedListener
的引用。 所以你的onResume()
可能看起來像這樣:
@Override
public void onResume() {
OnClickListener onClickListener = ((MyActivity) getActivity).getOnClickListener();
putIndicatorTabIndicatorOnClick(onClickListener);
}
由於您已在onResume()
設置它,因此應在onPause()
中將其刪除:
@Override
public void onPause() {
//set the onClickListener to null to free up the resource
}
使用像這樣的onResume()
和onPause()
來從監聽器中釋放資源是開發人員指南中推薦的方法。
當然,您必須通過檢查onCreate(Bundle savedInstanceState)
保存狀態並相應地恢復它來確保您的Activity也處理自己的生命周期。
請注意,可以通過多種方式觸發保存實例狀態和恢復:
您將能夠使用這些方法之一來確定您是否正確處理了活動和碎片的生命周期。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.