在片段中获取 null FragmentManager/Activity
Get null FragmentManager/Activity in fragment
场景
我想在收到一些 HTTP 请求的响应后更新几个 fragment
的内容。
我的想法
我的实现是这样的:
activity 的 onCreate
,绑定 ViewPagerAdapter
到它。然后触发HTTP请求获取数据。
请求成功后,更新Fragment中的内容。
代码
sendRequest
。 --> adapter.updateFragment(bundle)
--> fragment.updateData(bundle);
Activity
protected void onCreate(Bundle savedInstanceState) {
Log.d("DetailedProduct-LifeCycle", "------------onCreate------------");
...
// Set ViewPager
viewPager = findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
// Send Request
sendRequest();
...
}
public void sendRequest(){
Log.d("DetailedProduct", requestUrl);
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,
requestUrl,
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
LinearLayout progressView = findViewById(R.id.progressView);
progressView.setVisibility(View.GONE);
bundle.putString("detail", response.toString());
Log.d("DetailedProduct", "get data:"+response.toString());
Log.d("DetailedProduct", "final Data:" + bundle.toString());
adapter.updateFragment(bundle);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("DetailedProduct", "Cannot get detailed data");
}
});
queue.add(jsonObjectRequest);
}
适配器
public class ViewPagerAdapter extends FragmentPagerAdapter {
private SellerFragment sellerFragment;
private ShippingFragment shippingFragment;
private ProductSummaryFragment productSummaryFragment;
private FragmentManager fragManager;
public ViewPagerAdapter(FragmentManager fragmentManager){
super(fragmentManager);
sellerFragment = new SellerFragment();
shippingFragment = new ShippingFragment();
productSummaryFragment = new ProductSummaryFragment();
}
@NonNull
@Override
public Fragment getItem(int position) {
// ToDo:
Log.d("ViewPager", position+": ------------getItem----------");
switch (position){
case 0:
if(productSummaryFragment==null){
productSummaryFragment = new ProductSummaryFragment();
}
return productSummaryFragment;
case 1:
if(sellerFragment==null){
sellerFragment = new SellerFragment();
}
return sellerFragment;
case 2:
if(shippingFragment==null){
shippingFragment = new ShippingFragment();
}
return shippingFragment;
default:
return null;
}
}
@Override
public int getCount() {
return 3;
}
public void updateFragment(Bundle bundle){
Log.d("ViewPager", "------------updateData----------");
productSummaryFragment.updateData(bundle);
sellerFragment.updateData(bundle);
shippingFragment.updateData(bundle);
}
}
片段示例
public class ShippingFragment extends Fragment {
private TextView shippingSection;
protected JSONObject data;
private AppCompatActivity mActivity;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.shipping_fragment_layout, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
shippingSection = view.findViewById(R.id.shipping_info_section_content);
setData();
}
@Override
public void onAttach(@NonNull Context context) {
Log.d("ShippingFragment", "-----------onAttach----------");
super.onAttach(context);
if(context instanceof AppCompatActivity){
Log.d("ShippingFragment", "---------bind mActivity Success-------");
mActivity = (AppCompatActivity)context;
}
}
@Override
public void onDetach() {
Log.d("ShippingFragment", "-----------onDetach----------");
super.onDetach();
}
// Same for all fragments
public void updateData(Bundle bundle){
Log.d("ShippingFragment", "--------------updateData------------");
setArguments(bundle);
if(mActivity==null){
Log.e("ShippingFragment", "------------activity disappears----------");
}
FragmentManager fragmentManager = mActivity.getSupportFragmentManager();
fragmentManager.beginTransaction().detach(this).attach(this).commit();
}
}
问题
日志显示位置 0,1 的片段 updateData
运行良好。但它会导致位置 2 的片段出错。
我发现的区别是适配器没有为位置 2 调用 getItem
,这意味着 shippingFragment
的 onAttach
没有被调用。所以mActivity
不存在。
没有mActivity
,在shippingFragment
中使用getFragmentManager
,得到这个错误:
我的直觉告诉我问题一定出在adapter的工作流程或者fragmentManager事务。但是作为Android的初学者,我花了一整天的时间,毫无头绪。
如何解决?顺便问一下,有没有更好的方法来实现我的场景?
尝试调用 viewPager.setOffscreenPageLimit(3)
以确保在 activity 打开后所有 3 个片段都附加到 activity。
场景
我想在收到一些 HTTP 请求的响应后更新几个 fragment
的内容。
我的想法
我的实现是这样的:
onCreate
,绑定 ViewPagerAdapter
到它。然后触发HTTP请求获取数据。
请求成功后,更新Fragment中的内容。
代码
sendRequest
。 --> adapter.updateFragment(bundle)
--> fragment.updateData(bundle);
Activity
protected void onCreate(Bundle savedInstanceState) {
Log.d("DetailedProduct-LifeCycle", "------------onCreate------------");
...
// Set ViewPager
viewPager = findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
// Send Request
sendRequest();
...
}
public void sendRequest(){
Log.d("DetailedProduct", requestUrl);
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,
requestUrl,
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
LinearLayout progressView = findViewById(R.id.progressView);
progressView.setVisibility(View.GONE);
bundle.putString("detail", response.toString());
Log.d("DetailedProduct", "get data:"+response.toString());
Log.d("DetailedProduct", "final Data:" + bundle.toString());
adapter.updateFragment(bundle);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("DetailedProduct", "Cannot get detailed data");
}
});
queue.add(jsonObjectRequest);
}
适配器
public class ViewPagerAdapter extends FragmentPagerAdapter {
private SellerFragment sellerFragment;
private ShippingFragment shippingFragment;
private ProductSummaryFragment productSummaryFragment;
private FragmentManager fragManager;
public ViewPagerAdapter(FragmentManager fragmentManager){
super(fragmentManager);
sellerFragment = new SellerFragment();
shippingFragment = new ShippingFragment();
productSummaryFragment = new ProductSummaryFragment();
}
@NonNull
@Override
public Fragment getItem(int position) {
// ToDo:
Log.d("ViewPager", position+": ------------getItem----------");
switch (position){
case 0:
if(productSummaryFragment==null){
productSummaryFragment = new ProductSummaryFragment();
}
return productSummaryFragment;
case 1:
if(sellerFragment==null){
sellerFragment = new SellerFragment();
}
return sellerFragment;
case 2:
if(shippingFragment==null){
shippingFragment = new ShippingFragment();
}
return shippingFragment;
default:
return null;
}
}
@Override
public int getCount() {
return 3;
}
public void updateFragment(Bundle bundle){
Log.d("ViewPager", "------------updateData----------");
productSummaryFragment.updateData(bundle);
sellerFragment.updateData(bundle);
shippingFragment.updateData(bundle);
}
}
片段示例
public class ShippingFragment extends Fragment {
private TextView shippingSection;
protected JSONObject data;
private AppCompatActivity mActivity;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.shipping_fragment_layout, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
shippingSection = view.findViewById(R.id.shipping_info_section_content);
setData();
}
@Override
public void onAttach(@NonNull Context context) {
Log.d("ShippingFragment", "-----------onAttach----------");
super.onAttach(context);
if(context instanceof AppCompatActivity){
Log.d("ShippingFragment", "---------bind mActivity Success-------");
mActivity = (AppCompatActivity)context;
}
}
@Override
public void onDetach() {
Log.d("ShippingFragment", "-----------onDetach----------");
super.onDetach();
}
// Same for all fragments
public void updateData(Bundle bundle){
Log.d("ShippingFragment", "--------------updateData------------");
setArguments(bundle);
if(mActivity==null){
Log.e("ShippingFragment", "------------activity disappears----------");
}
FragmentManager fragmentManager = mActivity.getSupportFragmentManager();
fragmentManager.beginTransaction().detach(this).attach(this).commit();
}
}
问题
日志显示位置 0,1 的片段 updateData
运行良好。但它会导致位置 2 的片段出错。
我发现的区别是适配器没有为位置 2 调用 getItem
,这意味着 shippingFragment
的 onAttach
没有被调用。所以mActivity
不存在。
没有mActivity
,在shippingFragment
中使用getFragmentManager
,得到这个错误:
我的直觉告诉我问题一定出在adapter的工作流程或者fragmentManager事务。但是作为Android的初学者,我花了一整天的时间,毫无头绪。
如何解决?顺便问一下,有没有更好的方法来实现我的场景?
尝试调用 viewPager.setOffscreenPageLimit(3)
以确保在 activity 打开后所有 3 个片段都附加到 activity。