简体   繁体   English

NullPointerException TextView.setText(CharSequence),尚不清楚其如何仍然为null

[英]NullPointerException TextView.setText(CharSequence), not clear how its still null

I've been trying for a little bit now to just get my app launching again. 我一直在努力尝试让我的应用再次启动。 I modified how I pulled bitcoin price data to allow for user preferences. 我修改了提取比特币价格数据的方式,以适应用户的偏好。 However since doing this I get a NullPointerException from my TextView currentPriceDisplay elements method. 但是,由于这样做,我从TextView currentPriceDisplay元素方法中获得了NullPointerException。 currentPriceDisplay.setText(getmBitcoinPrice());

I have modified values throughout my code to prevent this variable from ever actually being null, I've also checked my nav_header_main.xml file to see if I was referencing the right TextView I am. 我在整个代码中都修改了值,以防止该变量实际为null,我还检查了nav_header_main.xml文件,以查看是否引用了正确的TextView。 So at this point pretty stumped and I have to go to the day job. 所以在这一点上,我很沮丧,我必须去做日常工作。 If you can have a look at my code and see if you notice anything that would be great. 如果您可以看一下我的代码,看看是否发现任何很棒的东西。

MainActivity: 主要活动:

package com.instacoind.www.coind;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.util.Log;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Set;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    private Double mBitcoinPrice = 0.0;
    public Double getmBitcoinPrice(){
        return mBitcoinPrice;
    }
    public void setmBitcoinPrice(Double price){
        this.mBitcoinPrice = price;
    }
    private Double mBitcoinPriceOld = 0.0;
    public Double getmBitcoinPriceOld(){
        return mBitcoinPriceOld;
    }
    public void setmBitcoinPriceOld(Double price){
        this.mBitcoinPriceOld = price;
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(mBitcoinPrice != 0.0) {
                    Snackbar.make(view, "Last Change: " + priceChange(), Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }else{
                    Snackbar.make(view, "SYNC FAILED ERROR::01", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            }
        });

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Intent start_settings = new Intent(this, SettingsActivity.class);
            startActivity(start_settings);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onStart(){
        super.onStart();
        updatePrice();
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camera) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    public void updatePrice(){
        GetBitcoinPrice worker = new GetBitcoinPrice();
        worker.execute(getPrefFiat(this), getPrefPriceIndex(this));
        refreshPriceDisplays();
    }
    public static String getPrefFiat(Context context){
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        return prefs.getString(context.getString(R.string.pref_currency_key),
                context.getString(R.string.pref_currency_def));
    }
    public static String getPrefPriceIndex(Context context){
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        return prefs.getString(context.getString(R.string.pref_source_key),
                context.getString(R.string.pref_source_default));
    }
    public String priceChange(){
        Double past = getmBitcoinPriceOld();
        Double pres = getmBitcoinPrice();
        Double change = 0.0;
        String fin = "price_change";
        if(past != null){
            if(pres >= past){
                change = pres - past;
                fin = "+ " + Double.toString(change);
            }else if(pres <= past){
                change = past - pres;
                fin = "- " + Double.toString(change);
            }
        }else{
            setmBitcoinPriceOld(getmBitcoinPrice());
        }
        return fin;
    }
    public void refreshPriceDisplays(){
        TextView PriceDisplay = (TextView) findViewById(R.id.current_price_display);
        String error = "No Bitcoin Price";
        try {
            Log.v("RefreshPriceDisplays", "mBitcoinPrice: " + Double.toString(getmBitcoinPrice()));
            PriceDisplay.setText(Double.toString(getmBitcoinPrice()));
        }catch(NullPointerException e) {
            Log.v("RefreshPriceDisplays", "mBitcoinPrice NULL");
            PriceDisplay.setText("ERR");
        }
    }


    private class GetBitcoinPrice extends AsyncTask<String, Void, Double> {

        public String mPrefFiat;
        public String mPrefIndex;

        protected Double doInBackground(String... params) {

            // These two need to be declared outside the try/catch
            // so that they can be closed in the finally block.
            HttpURLConnection urlConnection = null;
            BufferedReader reader = null;

            // Will contain the raw JSON response as a string.
            String bitcoinJsonStr = null;
            this.mPrefFiat = params[0];
            this.mPrefIndex = params[1];



            try {
                // Construct the URL for the OpenWeatherMap query
                // Possible parameters are avaiable at OWM's forecast API page, at
                // http://openweathermap.org/API#forecast
                URL url = new URL(buildUrl(this.mPrefFiat,this.mPrefIndex));

                // Create the request to Index Source, and open the connection
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestMethod("GET");
                urlConnection.connect();

                // Read the input stream into a String
                InputStream inputStream = urlConnection.getInputStream();
                StringBuffer buffer = new StringBuffer();
                if (inputStream == null) {
                    // Nothing to do.
                    bitcoinJsonStr = null;
                }
                reader = new BufferedReader(new InputStreamReader(inputStream));

                String line;
                while ((line = reader.readLine()) != null) {
                    // Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
                    // But it does make debugging a *lot* easier if you print out the completed
                    // buffer for debugging.
                    buffer.append(line + "\n");
                }

                if (buffer.length() == 0) {
                    // Stream was empty.  No point in parsing.
                    bitcoinJsonStr = null;
                }
                bitcoinJsonStr = buffer.toString();
            } catch (IOException e) {
                Log.e("GetBitcoinPrice", "Error ", e);
                // If the code didn't successfully get the price index data, there's no point in attemping
                // to parse it.
                bitcoinJsonStr = null;
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (final IOException e) {
                        Log.e("GetBitcoinPrice", "Error closing stream", e);
                    }
                }
            }
            if(this.mPrefIndex == "https://api.coindesk.com/v1/bpi/currentprice.json")
                return parseCoindesk(bitcoinJsonStr);
            else if (this.mPrefIndex == "https://api.coinbase.com/v2/prices/spot?currency=")
                return parseCoinbase(bitcoinJsonStr);
            else if (this.mPrefIndex == "https://www.okcoin.com/api/v1/ticker.do?symbol=")
                return parseOkcoin(bitcoinJsonStr);
            else if (this.mPrefIndex == "https://cex.io/api/ticker/BTC/")
                return parseCex(bitcoinJsonStr);
            else
                return 0.0;
        }
        private Double parseCex(String bitcoinJsonStr){
            Double price = 0.0;

            try {
                JSONObject obj = new JSONObject(bitcoinJsonStr);
                price = obj.getDouble("bid");
                Log.v("ConvertPriceStr", "Current Price is " + Double.toString(price));
                if (price == null){
                    Log.e("CEXParsing", "Parsed to Null");
                }

            }catch (JSONException x){
                Log.e("ConvertPriceStr", "Error Parsing bitcoinJsonStr");
            }
            return price;
        }
        private Double parseCoindesk(String bitcoinJsonStr){
            Double price = 0.0;

            try {
                JSONObject obj = new JSONObject(bitcoinJsonStr);
                JSONObject bpi = obj.getJSONObject("bpi");
                JSONObject usd = bpi.getJSONObject("USD");
                price = usd.getDouble("rate_float");
                Log.v("ConvertPriceStr", "Current Price is " + Double.toString(price));

            }catch (JSONException x){
                Log.e("ConvertPriceStr", "Error Parsing bitcoinJsonStr");
            }
            return price;
        }
        private Double parseCoinbase(String bitcoinJsonStr){
            Double price = 0.0;
            try{
                JSONObject obj = new JSONObject(bitcoinJsonStr);
                JSONObject bpi = obj.getJSONObject("data");
                price = bpi.getDouble("amount");
                Log.v("ParseCoinbase", "Current Price is " + Double.toString(price));
            }catch(JSONException e){
                Log.e("ParseCoinbase", "Error Parsing bitcoinJsonStr");
            }
            return price;
        }
        private Double parseOkcoin(String bitcoinJsonStr){
            Double price = 0.0;
            try{
                JSONObject obj = new JSONObject(bitcoinJsonStr);
                JSONObject bpi = obj.getJSONObject("ticker");
                price = bpi.getDouble("buy");
                Log.v("ParseOkCoin", "Current Price is " + Double.toString(price));
            }catch(JSONException e){
                Log.e("ParseOkCoin", "Error Parsing bitcoinJsonStr");
            }
            return price;
        }
        private String buildUrl(String prefFiat, String prefIndex){
            String url = null;
            try {
                if (prefIndex == "https://api.coinbase.com/v2/prices/spot?currency=") {
                    url = prefIndex + prefFiat;
                } else if (prefIndex == "https://api.coindesk.com/v1/bpi/currentprice.json") {
                    url = prefIndex + prefFiat;
                } else if (prefIndex == "https://www.okcoin.com/api/v1/ticker.do?symbol=") {
                    String modFiat;
                    modFiat = "btc_" + prefFiat;
                    url = prefIndex + modFiat;
                } else if (prefIndex == "https://cex.io/api/ticker/BTC/") {
                    String modFiat;
                    modFiat = prefIndex + prefFiat;
                    url = modFiat;
                } else {
                    url = "https://api.coindesk.com/v1/bpi/currentprice.json";
                }
            }catch(NullPointerException e){
                Log.e("URL Builder", "Error Constructing Proper URL", e);
            }
            return url;
        }

        protected void onPostExecute(Double result){
            setmBitcoinPriceOld(getmBitcoinPrice());
            setmBitcoinPrice(result);
        }
    }
}

XML Files: XML档案:

activity_main.xml: activity_main.xml:

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

app_bar_main.xml: app_bar_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.instacoind.www.coind.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/refresh_60_60" />

</android.support.design.widget.CoordinatorLayout>

content_main.xml: content_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.instacoind.www.coind.MainActivity"
    tools:showIn="@layout/app_bar_main">

</RelativeLayout>

nav_header_main.xml: nav_header_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/nav_header_height"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/coin_display"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:src="@drawable/bitcoin_80_80"
        android:contentDescription="@string/coin_content_description"/>

    <TextView
        android:id="@+id/bpi_source_display"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="BPI_Source"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

    <TextView
        android:id="@+id/def_currency_display"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:layout_toRightOf="@+id/bpi_source_display"
        android:layout_toEndOf="@+id/bpi_source_display"
        android:layout_alignParentBottom="true"
        android:text="DEF_Currency" />
    <TextView
        android:id="@+id/current_price_display"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="40dp"
        android:paddingStart="80dp"
        android:paddingLeft="80dp"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_toRightOf="@+id/coin_display"
        android:textAppearance="@style/TextAppearance.AppCompat.Headline"/>

</RelativeLayout>

I think the problem comes from these four method: parseCoindesk,parseCoinbase,parseCex,parseOkcoin 我认为问题来自以下四种方法:parseCoindesk,parseCoinbase,parseCex,parseOkcoin

In each of these(parseCex for example): 在每一个中(例如parseCex):

            if (price == null){
                Log.e("CEXParsing", "Parsed to Null");// You just print a Log!
            }

        }catch (JSONException x){
            Log.e("ConvertPriceStr", "Error Parsing bitcoinJsonStr");
        }
        return price;//when price is null it can still return!
    }

so, you should try to return like this: 因此,您应该尝试像这样返回:

return price == null ? 0.0 : price;

Ok, way longer than I thought it would take till I could actually sit down and work on this again. 好吧,比我想的要更长的时间,直到我可以真正坐下来再进行研究。 Apologies for dragging my heels, I have fixed the problem of the crash. 抱歉,我已经解决了崩溃的问题。

It occurred because I was calling my refreshPriceDisplays() method before the onCreate/AsyncTask was finished. 发生这种情况是因为我在onCreate / AsyncTask完成之前调用了refreshPriceDisplays()方法。 Once I moved refreshPriceDisplays() into my onPostExecute everything went great. 一旦将refreshPriceDisplays()移到onPostExecute中,一切就变得非常好。

And as far as the first answer to this question you raised some good points about my logic and they have been addressed as well thank you so much for your inputs! 关于这个问题的第一个答案,您对我的逻辑提出了一些意见,并且这些问题也已得到解决,也非常感谢您的投入!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 TextView.setText 抛出 NullPointerException 尽管给定的字符串不是 null - TextView.setText throws NullPointerException despite given String not being null TextView.setText()上的Java空指针异常 - Java null pointer exception on TextView.setText() Android中的TextView.setText - TextView.setText in Android 如何TextView.setText(List <String> 对象)来自List的TextView.setText(array [index])settext - how to TextView.setText(List<String>object) like TextView.setText(array[index]) settext from List 如何修复翻译不适用于TextView.setText()? - How to fix Translation not working with TextView.setText()? ANDROID适配器-getView方法处的NullPointerException(行:textView.setText()) - ANDROID adapter - NullPointerException at getView method (line : textView.setText()) textView.setText不起作用 - textView.setText not working ListView未加载,在textview.setText()上返回null对象。 - ListView not loading, returns null object on textview.setText(); TensorFlow Lite Android 应用程序在空对象引用上因 NullPointerException &#39;void android.widget.TextView.setText(java.lang.CharSequence)&#39; 崩溃 - TensorFlow Lite Android App crashes with NullPointerException 'void android.widget.TextView.setText(java.lang.CharSequence)' on null object reference 字符串编码TextView.setText() - String Encoding TextView.setText()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM