首页 > 解决方案 > setAdapter 方法中出现空对象引用错误

问题描述

我试图制作一个显示实时新闻的新闻应用程序,但出现空对象引用错误。

我的 Main.java 类:

 private NewsAdapter mAdapter;

      public final static String LOG_TAG = News.class.getName();

    private TextView mEmptyStateTextView;

    private static final int NEWS_LOADER_ID = 1;

    private ProgressBar progressBar = null;

    //Url for News
    private static final String GardianNewws = "https://content.guardianapis.com/search?q=debate&tag=politics/politics&from-date=2019-01-01&api-key=62d26206-4f2a-42a2-8927-79de5746bd1d";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //fins a refreence to the(@link ListView)in the Layout
        ListView NewsListView = (ListView)findViewById(R.id.list);

      NewsListView.setEmptyView(mEmptyStateTextView);

        //grab the progressbar
        progressBar = (ProgressBar)findViewById(R.id.loading_spinner);

        //create a new Adapter thet takes an empty list of earthquake
        mAdapter = new NewsAdapter(this,new ArrayList<News>());


       //set the adapter
        NewsListView.setAdapter(mAdapter);

        //set the item click listener on the ListView,which sends an intent
        //to open a website with more information about the selected News

        NewsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //Find the Current News that was Clicked on
                News currentNews = mAdapter.getItem(position);

                //convert the String URL into a URL obj;
                Uri newsUri = Uri.parse(currentNews.getUrl());

                //create a new Intent to view the news URI
                Intent websiteIntent = new Intent(Intent.ACTION_VIEW,newsUri);

                //start the Intent
                startActivity(websiteIntent);

            }
        });
    }
}

我的新闻构造函数类:

  //news serial
    private String mSerial;

    //main news title
    private String mTitle;

    //news feed
    private String mNewsFeed;

    //URL
    private String mUrl;

    public News(String serial,String title,String feed,String url){
        mSerial = serial;
        mTitle = title;
        mNewsFeed = feed;
        mUrl = url;
    }

    //get the News
    public String getSerial(){
        return mSerial;
    }

    public String getTitle(){
        return mTitle;
    }

    public String getNewsFeed(){
        return mNewsFeed;
    }
    public String getUrl(){
        return mUrl;
    }

我的 NetworkAdapter.java 类:

   private static final String LOG_TAG = NewsAdapter.class.getSimpleName();
    /**
     * this is custom constructor (it does not mirror a superclass constructor );
     * The context is used to inflate the layout file, and the list is the data we want
     * to populate into the lists
     * @param context The current context,Used to inflate the layout file
     *
     * @param News a list of words obj. to display in a list
     */

    public NewsAdapter(Context context, ArrayList<News>news) {
        super(context, 0,news);
    }


    @Override
    public View getView(int position,  View convertView,  ViewGroup parent) {
        View listItem = convertView;
        if (listItem == null){
            listItem = LayoutInflater.from(getContext()).inflate(R.layout.activity_main,parent,false);

        }

        //get the location of the obj.
        News currentposition = getItem(position);

        //find the textView
        TextView title = (TextView)listItem.findViewById(R.id.title);

        //set text on textView
        title.setText(currentposition.getTitle());

        //find the TextView
        TextView MainNews = (TextView)listItem.findViewById(R.id.main_news);

        //set the TextView
        MainNews.setText(currentposition.getNewsFeed());

        return listItem;
    }

我的 NewtorkUtils.java 类:

 /** Tag for the log messages */
    public static final String LOG_TAG = NewsQueryUtils.class.getSimpleName();

    /**
     * Create a private constructor because no one should ever create a {@link NewsQueryUtils} object.
     * This class is only meant to hold static variables and methods, which can be accessed
     * directly from the class name NewsQueryUtils (and an object instance of QueryUtils is not needed).
     */
    private NewsQueryUtils(){
    }

    //Query the News dataset and return an (@link Event) obj to represent an single earthquake
    public static List<News> fetchNewsQueryData(String requestUrl){
        try {
            Thread.sleep(2000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.i(LOG_TAG,"Test fetchNewsData called...");
        //create URL object
        URL url  = createUrl(requestUrl);

      //perform HTTP request to  the url and receive a JSON responce
        String jsonResponce = null;
        try {
            jsonResponce = makeHTTPRequest(url);
        } catch (IOException e){
            Log.e(LOG_TAG,"Error closing input stream",e);
        }

        List<News>news = eatractFeatureFromJSON(jsonResponce);

        //Return
        return news;
    }

    /**
     * Return new URL object from the given string URl
     */
    private static URL createUrl(String stringUrl){
        URL url = null;
        try {
            url = new URL(stringUrl);
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "Error with creating URL ", e);
            return null;
        }
        return url;
    }

    //Make an HTTP request to the given url and return a string
    private static String makeHTTPRequest(URL url) throws IOException{
        String jsonResponce = "";

        //if the URl is NULL, them retuen early
        if (url == null){
            return jsonResponce;
        }
        HttpURLConnection urlConnection = null;
        InputStream inputStream = null;
        try {
            urlConnection = (HttpURLConnection)url.openConnection();
            urlConnection.setConnectTimeout(10000/*millisecond*/);
            urlConnection.setReadTimeout(10000/*millisecond*/);
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            //if the request was successful (Responce code 200),
            //then read the input stream and parse the responce
            if (urlConnection.getResponseCode() == 200){
                inputStream = urlConnection.getInputStream();
                jsonResponce = readFromStream(inputStream);
            } else {
                Log.e(LOG_TAG,"Error responce code" + urlConnection.getResponseCode());

            }
        }catch (IOException e){
            Log.e(LOG_TAG,"Problem retrieving the earthquake JSON results.", e);

        } finally {
            if (urlConnection != null){
                // Closing the input stream could throw an IOException, which is why
                // the makeHttpRequest(URL url) method signature specifies than an IOException
                // could be thrown.
                inputStream.close();
            }
        }
        return jsonResponce;
    }
    /**
     * Convert the {@link InputStream} into a String which contains the
     * whole JSON response from the server.
     */
    private static String readFromStream(InputStream inputStream) throws IOException{
        StringBuilder output = new StringBuilder();
        if (inputStream != null){
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader reader = new BufferedReader(inputStreamReader);
            String line = reader.readLine();
            while (line != null){
                output.append(line);
                line = reader.readLine();
            }
        }
        return output.toString();
    }

    /**
     * Return a list of (@link News)obj. that has been built up from
     * parsing a JSON responce
     */
    private static List<News>eatractFeatureFromJSON(String newsJson){
        //if the json string is empty or null,then return early
        if (TextUtils.isEmpty(newsJson)){
            return null;
        }
        //Create an empty Array
        List<News>newss = new ArrayList<>();

        try {
            JSONObject baseJsonResponce = new JSONObject(newsJson);
            JSONArray newsArray = baseJsonResponce.getJSONArray("response");

            for (int i = 0;i<newsArray.length();i++){
                JSONObject currentNews = newsArray.getJSONObject(i);
                JSONObject properties = currentNews.getJSONObject("results");
                String id = properties.getString("id");

                String sectionId = properties.getString("sectionId");
                String webttitle=  properties.getString("webTitle");

                // Extract the value for the key called "url"
                String url = properties.getString("webUrl");

                News news = new News(id,sectionId,webttitle,url);
                newss.add(news);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return newss;
    }

我的 ListView.Xml 类:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/list"
        android:dividerHeight="1dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </ListView>
    <!-- empty text view -->
    <TextView
        android:id="@+id/emptyView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textAppearance="?android:textAppearanceMedium"
        android:text="center"/>

    <!-- progress view -->
    <ProgressBar
        android:id="@+id/loading_spinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>

</RelativeLayout>

我的 Activity_Main.xml 类:

<LinearLayout 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:orientation="horizontal"
    android:paddingStart="16dp"
    android:paddingLeft="16dp"
    android:paddingEnd="16dp"
    android:paddingRight="16dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/serial"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:fontFamily="sans-serif"
        android:gravity="center"
        android:textColor="@android:color/black"
        android:textSize="16dp"
        android:tooltipText="1" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:ellipsize="end"
            android:fontFamily="sans-serif"
            android:maxLines="1"
            android:textAllCaps="true"
            android:textColor="@color/colorPrimary"
            android:textSize="12dp"
            android:tooltipText="Heading" />

        <TextView
            android:id="@+id/main_news"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="2"
            android:textSize="12dp"
            android:tooltipText="here" />
    </LinearLayout>

</LinearLayout>

我的错误:

Caused by: java.lang.NullPointerException:   
Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)'   
on a null object reference at com.example.user.worldnews.MainActivity.onCreate(MainActivity.java:46)  

标签: androidandroid-studionullpointerexception

解决方案


以下错误:

Caused by: java.lang.NullPointerException:   
Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)'   
on a null object reference at com.example.user.worldnews.MainActivity.onCreate(MainActivity.java:46) 

是因为您的activity_main.xml.

将以下 ListView 添加到您的 xml:

  <ListView
        android:id="@+id/list"
        android:dividerHeight="1dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

推荐阅读