2016-09-28 64 views
-3

我必须在Android中创建应用程序。我已经成功调试了几个错误,但我不明白这一个:如何避免此java.lang.NullPointerException?

FATAL EXCEPTION: main 
Process: com.example.android.bookapp, PID: 7450 
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' 
on a null object reference 

我可以看到,Android的工作室把橙色背景警告我说,我的代码的某些部分可能会产生显示java.lang.NullPointerException ,但我没有看到要改变什么以避免这种情况发生,而且我甚至不知道为什么在运行我的应用程序时发生此错误。

这里是我的代码:

public class MainActivity extends AppCompatActivity { 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    /** find the button view, set an onclick listener on it, define & execute the bookListAsyncTask */ 
    Button searchButton = (Button) findViewById(R.id.search_button); 
    searchButton.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      BookListAsyncTask bookListAsyncTask = new BookListAsyncTask(); 
      bookListAsyncTask.execute(); 
     } 
    }); 
} 

/** 
* define the URL 
*/ 
public String makeUrl() { 
    EditText searchBookEditText = (EditText) findViewById(R.id.search_edit_text); 
    String searchBook = searchBookEditText.getText().toString(); 
    String searchBookModified = searchBook.replaceAll(" ", "+"); 
    final String REQUEST_URL = "https://www.googleapis.com/books/v1/volumes?q=" + searchBookModified + "&maxResults=3&printType=books"; 
    return REQUEST_URL; 
} 

private class BookListAsyncTask extends AsyncTask<URL, Void, ArrayList<Book>> { 

    @Override 
    protected ArrayList<Book> doInBackground(URL... urls) { 
     // Create URL object 
     URL url = createUrl(makeUrl()); 

     // Perform HTTP request to the URL and receive a JSON response back 
     String jsonResponse = ""; 
     try { 
      jsonResponse = makeHttpRequest(url); 
     } catch (IOException e) { 
     } 

     // Extract relevant fields from the JSON response and create an ArrayList<Book> object 
     ArrayList<Book> allBooks = extractFeatureFromJson(jsonResponse); 

     return allBooks; 
    } 

    /** 
    * Update the screen with the given books (which was the result of the 
    * {@link BookListAsyncTask}). 
    */ 
    @Override 
    protected void onPostExecute(ArrayList<Book> allBooks) { 
     if (allBooks == null) { 
      return; 
     } 
     BookAdapter bookAdapter = new BookAdapter(MainActivity.this, allBooks); 
     ListView listView = (ListView) findViewById(R.id.list_view); 
     listView.setAdapter(bookAdapter); 
    } 

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

    /** 
    * Make an HTTP request to the given URL and return a String as the response. 
    */ 
    private String makeHttpRequest(URL url) throws IOException { 
     String jsonResponse = ""; 
     HttpURLConnection urlConnection = null; 
     InputStream inputStream = null; 
     try { 
      urlConnection = (HttpURLConnection) url.openConnection(); 
      urlConnection.setRequestMethod("GET"); 
      urlConnection.setReadTimeout(10000 /* milliseconds */); 
      urlConnection.setConnectTimeout(15000 /* milliseconds */); 
      urlConnection.connect(); 
      inputStream = urlConnection.getInputStream(); 
      int responseCode = urlConnection.getResponseCode(); 
      if (responseCode == 200) { 
       jsonResponse = readFromStream(inputStream); 
      } else { 
       jsonResponse = ""; 
       Log.e("MainActivity", "error response code" + String.valueOf(responseCode)); 
      } 

     } catch (IOException e) { 
      // TODO: Handle the exception 
      Log.e("MainActivity", "Problem retrieving the earthquake JSON results", e); 

     } finally { 
      if (urlConnection != null) { 
       urlConnection.disconnect(); 
      } 
      if (inputStream != null) { 
       // function must handle java.io.IOException here 
       inputStream.close(); 
      } 
     } 
     return jsonResponse; 
    } 

    /** 
    * Convert the {@link InputStream} into a String which contains the 
    * whole JSON response from the server. 
    */ 
    private String readFromStream(InputStream inputStream) throws IOException { 
     StringBuilder output = new StringBuilder(); 
     if (inputStream != null) { 
      InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8")); 
      BufferedReader reader = new BufferedReader(inputStreamReader); 
      String line = reader.readLine(); 
      while (line != null) { 
       output.append(line); 
       line = reader.readLine(); 
      } 
     } 
     return output.toString(); 
    } 

    /** 
    * Return a book ArrayList 
    */ 
    public ArrayList<Book> extractFeatureFromJson(String bookJSON) { 

     ArrayList<Book> allBooks = new ArrayList<>(); 
     try { 
      JSONObject baseJsonResponse = new JSONObject(bookJSON); 
      JSONArray items = baseJsonResponse.getJSONArray("items"); 

      // If there are results in the features array 
      if (items.length() > 0) { 
       for (int i = 0; i < items.length(); i++) 
       // Parse the JSON and fill the allBooks ArrayList) 
       { 
        JSONObject currentBook = items.getJSONObject(i); 
        JSONObject currentVolumeInfo = currentBook.getJSONObject("volumeInfo"); 
        String currentTitle = currentVolumeInfo.getString("title"); 
        String currentFirstAuthor = "Author Unknown"; 
        Book book = new Book(currentTitle, currentFirstAuthor); 
        allBooks.add(book); 
       } 

       return allBooks; 
      } 
     } catch (JSONException e) { 
      Log.e("MainActivity", "Problem parsing the earthquake JSON results", e); 
     } 
     return null; 
    } 
} 


public class BookAdapter extends ArrayAdapter<Book> { 

    public BookAdapter(Activity context, ArrayList<Book> books) { 
     super(context, 0, books); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     // Check if the existing view is being reused, otherwise inflate the view 
     View listItemView = convertView; 
     if (listItemView == null) { 
      listItemView = LayoutInflater.from(getContext()).inflate(
        R.layout.list_item_view, parent, false); 
     } 

     Book currentBook = getItem(position); 

     TextView title = (TextView) findViewById(R.id.title_text_view); 
     title.setText(currentBook.getTitle()); 

     TextView author = (TextView) findViewById(R.id.author_text_view); 
     author.setText(currentBook.getAuthor()); 

     return listItemView; 
    } 
} 
} 

和书类,我修改了一下get方法,但它并没有帮助:

public class Book { 

private String mTitle; 
private String mAuthor; 

public Book(String title, String author){ 
    mTitle = title; 
    mAuthor = author; 
} 

public String getTitle(){ 
    if (mTitle == null){ 
     return mTitle = "";} 
    else {return mTitle;}} 
public String getAuthor(){ 
    if (mAuthor == null){ 
     return mAuthor = ""; 
    } else {return mAuthor;}} 
} 

你看到了什么问题?

+0

正上方author.setText(...)被调用。 – Corgs

+0

由于某种原因,标题或书籍为空。检查你的XML是否具有这样的变量名称。 – Corgs

+0

告诉你在哪里,你是例外 –

回答

4

更改线路

TextView title = (TextView) findViewById(R.id.title_text_view); 
TextView author = (TextView) findViewById(R.id.author_text_view); 

TextView title = (TextView) listItemView.findViewById(R.id.title_text_view); 
TextView author = (TextView) listItemView.findViewById(R.id.author_text_view); 



@Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      // Check if the existing view is being reused, otherwise inflate the view 
      View listItemView = convertView; 
      if (listItemView == null) { 
       listItemView = LayoutInflater.from(getContext()).inflate(
         R.layout.list_item_view, parent, false); 
      } 

      Book currentBook = getItem(position); 

      TextView title = (TextView) listItemView.findViewById(R.id.title_text_view); 
      title.setText(currentBook.getTitle()); 

      TextView author = (TextView) listItemView.findViewById(R.id.author_text_view); 
      author.setText(currentBook.getAuthor()); 

      return listItemView; 
     } 
+0

希望解决方案为你工作..请接受答案.. – somia

+0

大家好,谢谢你的回答。索尼娅我按照你的建议改变了listItemView.findViewById的findViewById,它现在可以工作。谢谢 !你能解释一下为什么它有效吗?我真的不明白,我的标题和作者textview仍然可以为空,因为那里没有更多的NullPointerException警报。 – Alex9494

+0

此链接将会有用。 https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/ – somia