片段更改崩溃

Posted

技术标签:

【中文标题】片段更改崩溃【英文标题】:Crash on Fragment Change 【发布时间】:2019-02-20 19:12:28 【问题描述】:

这是我的片段之一的代码 sn-p:

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

    View view = inflater.inflate(R.layout.fragment_three, container, false);

 listView = (ListView)view.findViewById(R.id.list_listview);
        adapter=new list_adapter(getActivity(),transaction_list);
        transaction_list.clear();
        listView.setAdapter(adapter);
        setListViewData();
return view;



private void setListViewData() 

        RequestQueue requestQueue = Volley.newRequestQueue(getContext());
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, listurl, null,
                new Response.Listener<JSONArray>() 
            public void onResponse(JSONArray jsonArray) 
                if (jsonArray.length() > 0) 
                    Log.e("JSON ARRAY", jsonArray.toString());


                    for (int i = 0; i < jsonArray.length(); i++) 
                        try 

                            JSONObject obj = jsonArray.getJSONObject(i);
                            User user = new User();

                            User.setmName(obj.getString("name"));
                            User.setmnName(obj.getString("nname"));
                            User.setmDate(obj.getString("date"));
                            User.setmProfile(obj.getString("profile"));
                            user.setmDirection(obj.getString("direction"));


                            transaction_list.add(user);

                         catch (JSONException e) 
                            e.printStackTrace();
                        
                        adapter.notifyDataSetChanged();
                    
                    try 
                        info.setText(getView().getResources().getString(R.string.user_rest, jsonArray.getJSONObject(0).getString("info")));

            Button edit = getActivity().findViewById(R.id.button_edit);
            edit.setClickable(true);

                     catch (JSONException e) 
                        e.printStackTrace();
                    
                


            


        , new Response.ErrorListener() 
            @Override
            public void onErrorResponse(VolleyError volleyError) 
                Log.e("Error", String.valueOf(volleyError));
            
        );

        // add json array request to the request queue
        requestQueue.add(jsonArrayRequest);


    

代码工作正常,但是当我在处理 Volley 请求时切换到另一个片段时(基本上是在片段从服务器加载数据时),应用程序崩溃,给我以下错误:

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“android.content.res.Resources android.view.View.getResources()” .onResponse(fragment_three.java:178) .onResponse(fragment_three.java:151)

第 178 行: info.setText(getView().getResources().getString(R.string.user_rest, jsonArray.getJSONObject(0).getString("info")));

第 151 行: 新的 Response.Listener()

第 178 行中的错误以某种方式清楚为什么会发生,但我怎样才能防止它发生呢?

第 151 行的错误有点奇怪,是否可能是因为在“Volley.newRequestQueue(getContext());”之前的行中,当我切换到另一个片段时,getContext() 为“null”或者是这样包含所有片段的 Main Activity 的上下文(因此在通过菜单时它基本上永远不会为空)?

【问题讨论】:

我相信 getView() 是空的 【参考方案1】:

堆栈跟踪的第一行告诉你getView() 正在返回null,我想你已经知道了。堆栈跟踪的第二行是它的“原因”,它只是告诉您该调用来自“哪里”:请求的响应侦听器。

这里发生的事情的根本原因是离开您的 Fragment 的导航导致 Android 框架破坏了您的 Fragment。该过程的一部分是您的 Fragment 的 onDestroyView() 方法将被调用,之后 getView() 将返回 null

要修复崩溃,您可以执行以下两项操作之一。

最简单的方法是将您的电话转入if (getView() != null)。这将暂时解决问题,但这是一种快速而肮脏的事情。

更好的解决方案是利用 Android 框架调用 Fragment 的 onDestroyView() 来取消 Volley 请求。这样(a)您的应用程序不会在它不会使用的网络调用上做无用的工作,并且(b)您不必担心是否会在其中添加一些其他容易崩溃的代码未来。

可能最简单的做法是在 Fragment 的类级别(在 setListViewData() 方法之外)声明 JsonArrayRequest jsonArrayRequest 变量,然后在 onDestroyView() 中清理它:

JsonArrayRequest jsonArrayRequest;

private void setListViewData() 
    RequestQueue requestQueue = Volley.newRequestQueue(getContext());
    jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, listurl, null,
            new Response.Listener<JSONArray>() 
                ...
            );


@Override
public void onDestroyView() 
    if (jsonArrayRequest != null) 
        jsonArrayRequest.cancel();
    

【讨论】:

那是要走的。我使用此代码并尝试在解析 jsonArray 时启用 Button,并且我得到另一个“NullPointerException:尝试在空对象引用上调用虚拟方法 'void android.widget.Button.setClickable(boolean)'”。如果 !=null ,我是否必须检查与 jsonArray 请求相关的每个操作? 看看我的编辑,我说的是“按钮编辑” 您确定要拨打getActivity().findViewById() 吗?这将在活动的布局中查找按钮,但我假设您想在片段的布局中找到它。请改用getView().findViewById() 不,是 getResources() 导致错误,我在 onCreateView 之外的类中调用它。 java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法 'android.content.res.Resources android.view.View.getResources()'【参考方案2】:

替换这一行:

info.setText(getView().getResources().getString(R.string.user_rest, jsonArray.getJSONObject(0).getString("info")));

与:

info.setText(getActivity().getResources().getString(R.string.user_rest, jsonArray.getJSONObject(0).getString("info")));

注意这一点:

 setListViewData(); //call function(getView()) before really get view.
 return view;//only after this line the view returnd.

【讨论】:

是的,但是...我不能将 setListViewData() 放在返回视图之后。所以我真的不明白你的暗示!无论如何谢谢!【参考方案3】:

关注这个 github repo 以帮助您在片段之间导航 https://github.com/SWAQ-COMMUNITY/SliderModule.git 然后我认为你需要在你的 res 文件夹中做一些调整,检查你是否有类似 drawable-v21 或类似文件夹的东西,将内容移动到像这样 drawable 的文件夹

例如移动drawable-v21中的所有内容>drawable

并对 mimap 和 value 应用相同的内容。然后删除那些文件夹...

此文件夹 drawable-v21 和类似 无效并重新启动,那么你应该没问题

【讨论】:

以上是关于片段更改崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Android Studio - 在片段之间更改时底部导航崩溃

每当我尝试从 Fragment java 文件中更改片段的某些属性时,应用程序就会崩溃

Android - 应用程序启动时片段 onCreate 崩溃

片段在重新加载时崩溃

将片段与 GoogleMap 一起使用时应用程序崩溃

片段崩溃与 setOnClickListener