java.lang.NullPointerException:尝试调用虚方法' android.content.res.Resources android.content.Context.getResources()

时间:2016-05-19 13:25:57

标签: android nullpointerexception

我正在从网上抓一个html页面。该页面包含图像,我使用 UILImageGetter 加载图像。

问题在于,如果页面刚刚开始加载并且我多次旋转设备,则应用程序会因NPE而崩溃。

UILImageGetter

public class UILImageGetter implements Html.ImageGetter{
    Context c;
    TextView container;
    UrlImageDownloader urlDrawable;


    public UILImageGetter(View textView, Context context) {
        this.c = context;
        this.container = (TextView) textView;
    }

    @Override
    public Drawable getDrawable(String source) {
        urlDrawable = new UrlImageDownloader(c.getResources(), source);
        if (Build.VERSION.SDK_INT >= 21) {
        urlDrawable.mDrawable = c.getResources().getDrawable(R.drawable.default_thumb,null);
        } else {
            urlDrawable.mDrawable = c.getResources().getDrawable(R.drawable.default_thumb);
        }
        ImageLoader.getInstance().loadImage(source, new SimpleListener(urlDrawable));
        return urlDrawable;
    }

    private class SimpleListener extends SimpleImageLoadingListener {
        UrlImageDownloader mUrlImageDownloader;

        public SimpleListener(UrlImageDownloader downloader) {
            super();
            mUrlImageDownloader= downloader;
        }

        @Override
        public void onLoadingStarted(String imageUri, View view) {
            Log.d("DEBUG", "onLoadingStarted called");
            //spinner.setVisibility(View.VISIBLE);

        }

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
            //spinner.setVisibility(View.GONE);

            int width = loadedImage.getWidth();
            int height = loadedImage.getHeight();

            int newWidth = width;
            int newHeight = height;

            if (width > container.getWidth()) {
                newWidth = container.getWidth();
                newHeight = (newWidth * height) / width;
            }

            if (view != null) {
                container.getLayoutParams().width = newWidth;
                container.getLayoutParams().height = newHeight;
            }

            Drawable result = new BitmapDrawable(c.getResources(), loadedImage);
            result.setBounds(0, 0, newWidth, newHeight);

            mUrlImageDownloader.setBounds(1, 1, newWidth, newHeight);
            mUrlImageDownloader.mDrawable = result;
            container.invalidate();

            container.setText(container.getText());

        }

        @Override
        public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
            String message = null;
            switch (failReason.getType()) {
                case IO_ERROR:
                    message = "Input/Output error";
                    break;
                case DECODING_ERROR:
                    message = "Image can't be decoded";
                    break;
                case NETWORK_DENIED:
                    message = "Downloads are denied";
                    break;
                case OUT_OF_MEMORY:
                    message = "Out Of Memory error";
                    break;
                case UNKNOWN:
                    message = "Unknown error";
                    break;
            }
            Toast.makeText(view.getContext(), message, Toast.LENGTH_SHORT).show();
            //spinner.setVisibility(View.GONE);
        }
    }

    private class UrlImageDownloader extends BitmapDrawable {
        public  Drawable mDrawable;

        public UrlImageDownloader(Resources resources, String filepath) {
            super(resources, filepath);
            mDrawable = new BitmapDrawable(resources, filepath);
        }

        @Override
        public void draw(Canvas canvas) {
            if (mDrawable != null) {
                mDrawable.draw(canvas);
            }
        }
    }
}

DetailsFragment

public class DetailsFragment extends Fragment implements ObservableScrollViewCallbacks{


    private AlertDialog internetDialog;
    private AlertDialog sthWrongAlert;
    private String url;

    private String birdData;

    private final String TAG = "DetailsFragment";
    protected com.nostra13.universalimageloader.core.ImageLoader mImageLoader;


    TextView birdContent;
    public DetailsFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        url = getArguments().getString("bird_link");

        // Inflate the layout for this fragment
        view =  inflater.inflate(R.layout.fragment_details, container, false);

        showDialog();
        sthWrongDialog();

        gadContent = (TextView) view.findViewById(R.id.gad_content);


        DisplayImageOptions defaultoptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity())
                .defaultDisplayImageOptions(defaultoptions)
                .writeDebugLogs()
                .build();


        mImageLoader = com.nostra13.universalimageloader.core.ImageLoader.getInstance();
        mImageLoader.init(config);





        if (savedInstanceState != null) {
            birdData = savedInstanceState.getString("birdData");
            if (birdData != null) {
                parseHtml(birdData);
            } 
            } else if (NetworkCheck.isAvailableAndConnected(getActivity())){
                    loadBird();
                } 
            }
        } else {
            if (NetworkCheck.isAvailableAndConnected(getActivity())) {
                    loadGad();
                }
            } else {
                internetDialog.show();
            }
        }
        return view;
    }


    public interface OnLinkClickedListener {
        public void OnLinkClicked (String link);
    }

    private static OnLinkClickedListener sLinkCallbacks = new OnLinkClickedListener() {
        @Override
        public void OnLinkClicked(String link) {

        }
    };


    private void showDialog() {
        internetDialog = new AlertDialog.Builder(getActivity())
                // The usuals
                .create();
    }

    private void sthWrongDialog() {
        sthWrongAlert = new AlertDialog.Builder(getActivity())
                // The usuals
                .create();
    }

    private void loadBird() {
        Log.d(TAG, "loadBird called");

        final ProgressBar progressBar;
        progressBar = (ProgressBar) view.findViewById(R.id.progress_circle);
        progressBar.setVisibility(View.VISIBLE);


//        String news_id = getIntent().getStringExtra("BirdId");
        Log.d(TAG, "You clicked bird id " + url);

        StringRequest stringRequest = new StringRequest(url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        //Log.d("Debug", response.toString());
                        if (progressBar != null) {
                            progressBar.setVisibility(View.GONE);
                        }
                        parseHtml(response);
                        birdData = response;


                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        VolleyLog.d(TAG, "Error: " + error.getMessage());

                        if (progressBar != null) {
                            progressBar.setVisibility(View.GONE);
                        }
                        if (sthWrongAlert != null) {
                            sthWrongAlert.show();
                        }


                    }
                });

        //Creating requestqueue
        RequestQueue requestQueue = Volley.newRequestQueue(getActivity());

        //Adding request queue
        requestQueue.add(stringRequest);
    }

    private void parseHtml(String response) {
        Log.d(TAG, "parsinghtml");
        Document document = Jsoup.parse(response);
        bird_content = document.select("div.entry-content").first().html();
        setTextViewHTML(birdContent, bird_content);
    protected void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span)
    {
        int start = strBuilder.getSpanStart(span);
        int end = strBuilder.getSpanEnd(span);
        int flags = strBuilder.getSpanFlags(span);
        ClickableSpan clickable = new ClickableSpan() {
            public void onClick(View view) {
                Log.e(TAG, "on click" + span.getURL());
            }
        };
        strBuilder.setSpan(clickable, start, end, flags);
        strBuilder.removeSpan(span);
    }

    protected void setTextViewHTML(TextView text, String html) {
        CharSequence sequence = Html.fromHtml(html, new UILImageGetter(birdContent, getActivity()), null);
        SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
        URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class);
        for(URLSpan span : urls) {
            makeLinkClickable(strBuilder, span);
        }
        text.setText(strBuilder);
        text.setMovementMethod(LinkMovementMethod.getInstance());
    }

       @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (birdData != null) {
            outState.putString("birdData", birdData);
        }

        if (internetDialog != null) {
            outState.putBundle("internetDialog", internetDialog.onSaveInstanceState());
        }
        if (sthWrongAlert != null) {
            outState.putBundle("sthWrongAlert", sthWrongAlert.onSaveInstanceState());
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState != null) {
            if (internetDialog != null) {
                internetDialog.onRestoreInstanceState(savedInstanceState.getBundle("internetDialog"));
            }
            if (sthWrongAlert != null) {
                sthWrongAlert.onRestoreInstanceState(savedInstanceState.getBundle("sthWrongAlert"));

            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy called");
        if (mImageLoader.isInited()) {
            mImageLoader.destroy();
        }


        if (internetDialog != null){
            internetDialog.dismiss();
            internetDialog = null;
        }
        if (sthWrongAlert != null) {
            sthWrongAlert.dismiss();
            sthWrongAlert = null;
        }
    }

}

栈跟踪

05-19 13:37:14.936 12213-12213/com.pexample.birds E/AndroidRuntime: FATAL EXCEPTION: main
                                                                     Process: com.pexample.birds, PID: 12213
                                                                     java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
                                                                         at com.pexample.birds.UILImageGetter.getDrawable(UILImageGetter.java:39)
                                                                         at android.text.HtmlToSpannedConverter.startImg(Html.java:634)
                                                                         at android.text.HtmlToSpannedConverter.handleStartTag(Html.java:520)
                                                                         at android.text.HtmlToSpannedConverter.startElement(Html.java:761)
                                                                         at org.ccil.cowan.tagsoup.Parser.push(Parser.java:794)
                                                                         at org.ccil.cowan.tagsoup.Parser.rectify(Parser.java:1061)
                                                                         at org.ccil.cowan.tagsoup.Parser.stagc(Parser.java:1016)
                                                                         at org.ccil.cowan.tagsoup.HTMLScanner.scan(HTMLScanner.java:624)
                                                                         at org.ccil.cowan.tagsoup.Parser.parse(Parser.java:449)
                                                                         at android.text.HtmlToSpannedConverter.convert(Html.java:442)
                                                                         at android.text.Html.fromHtml(Html.java:136)
                                                                         at com.pexample.birds.DetailsFragment.setTextViewHTML(DetailsFragment.java:400)
                                                                         at com.pexample.birds.DetailsFragment.parseHtml(DetailsFragment.java:350)
                                                                         at com.pexample.birds.DetailsFragment.access$500(DetailsFragment.java:48)
                                                                         at com.pexample.birds.DetailsFragment$6.onResponse(DetailsFragment.java:291)
                                                                         at com.pexample.birds.DetailsFragment$6.onResponse(DetailsFragment.java:284)
                                                                         at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60)
                                                                         at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
                                                                         at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
                                                                         at android.os.Handler.handleCallback(Handler.java:739)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                         at android.os.Looper.loop(Looper.java:135)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:5910)
                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                         at java.lang.reflect.Method.invoke(Method.java:372)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)

在堆栈跟踪中,第39行在 UILImageGetter 中为urlDrawable = new UrlImageDownloader(c.getResources(), source);,第400行与第CharSequence sequence = Html.fromHtml(html, new UILImageGetter(birdContent, getActivity()), null);行相对应 在 DetailsFragment

请问,我该如何解决这个问题?

请不要a duplicate of this question。我知道什么是NPE以及是什么导致它,也许我错了,但我也知道我必须在行urlDrawable = new UrlImageDownloader(c.getResources(), source);之前检查资源是否为空但我不知道该怎么做。我迷路了,请帮助我。

修改

onCreate of hosting Activity

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_post);


        getWindow().getDecorView().setBackgroundColor(Color.WHITE);

        String bird_id = getIntent().getStringExtra("BirdId");
        Log.d(TAG,  bird_id);

        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        if (savedInstanceState == null) {
            Bundle bundle = new Bundle();
            Fragment fragment;

            fragment = new DetailsFragment();
            bundle.putString("bird_link", bird_id);
            fragment.setArguments(bundle);

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.setCustomAnimations(android.R.anim.slide_out_right, android.R.anim.slide_in_left, android.R.anim.slide_out_right, android.R.anim.slide_in_left);
            ft.add(R.id.post_frame, fragment);
            ft.commit();
        }

        if (savedInstanceState != null) {
            mContent = getSupportFragmentManager().getFragment(savedInstanceState, "mContent");
        }



    }

3 个答案:

答案 0 :(得分:0)

当您从纵向转移到横向时,您的活动将重新启动。当你第一次开始时,你的上下文不是null,但是当你更改屏幕时,你的上下文将为null,你的应用程序将崩溃。我建议你只需在清单文件中设置屏幕方向肖像。 像这样

<activity
        android:name="..."
        android:label="@string/app_name"
        android:screenOrientation="portrait"/>

答案 1 :(得分:0)

由于您的上下文在某些事件中为空,因此您需要更新片段&amp;的onAttach(mcontext)中的上下文。还有其他方法可以摆脱这个问题:

1)使用android:configChanges="orientation|screenSize|keyboardHidden"

保留片段实例

2)在清单中使用此标志反对活动以摆脱它double total = db.tblCustomerOrders.Where(x => x.CustomerID == customer.CustomerID).Select(t => t.Amount ?? 0).Sum();

答案 2 :(得分:0)

我已经创建了新的Class,用于检查网络连接是否可用,还使用BroadcastReceiver。

ConnectivityStatus.java

 public class ConnectivityStatus extends ContextWrapper {
public ConnectivityStatus(Context base) {
    super(base);
}

//checking for network connection
public static boolean isNetworkAvailable(Context context) {
    try {
        ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    /*
            if connected or connecting in network then return true
     */
        return networkInfo != null && networkInfo.isConnectedOrConnecting();
    }
   catch (NullPointerException e)
   {
       return false;
   }
}}

<强> DealerLocator.java

public class DealerLocator extends Fragment {
FragmentDealerLocatorBinding fragmentDealerLocatorBinding;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    getContext().registerReceiver(broadcastReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); //for checking network connection

    // Inflate the layout for this fragment
    fragmentDealerLocatorBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_dealer_locator, container, false);
    return fragmentDealerLocatorBinding.getRoot();
}

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (!ConnectivityStatus.isNetworkAvailable(getContext())) {
            Toast.makeText(context,"No Connection is available", Toast.LENGTH_SHORT).show();
        } else {
                //if connection available then write your code here
        }
    }
};
}

DealerLocator是扩展Fragment的类,我在这个类中有检查条件用于网络连接。 通常在Toast中,第一个参数是getContext(),但对于扩展Fragment的Class,我将该参数更改为上下文,可以从public void onReceive(Context context, Intent intent)方法访问。因此,使用此代码,我的应用程序运行完美。

我在清单文件中添加了三个权限来检查网络连接

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />