我刚开始学习android并且目前正在尝试创建一个可以使用URL获取数据的书籍列表应用程序,我目前正在使用自定义的arrayadapter(bookadapter)和listview以及自定义的asynctask(bookasynstask)。我希望在模拟器上看到一些信息,但我在仿真上看到的唯一一件事就是图书清单布局,没有关于图书的任何信息。
这是BookAdapter类
public class BookAdapter extends ArrayAdapter<Book> {
public BookAdapter(@NonNull Context context, @NonNull ArrayList<Book> books) {
super(context, 0, books);
}
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View listItemView = convertView;
if(listItemView==null){
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.book_item,parent,false);
}
Book book = getItem(position);
ImageView image = listItemView.findViewById(R.id.iamge_view);
//haven't figured out how to set image from url yet.
image.setImageResource(R.mipmap.ic_launcher);
TextView title = listItemView.findViewById(R.id.title_view);
title.setText(book.getTitle1());
TextView authors = listItemView.findViewById(R.id.author_view);
authors.setText(book.getAuthors());
TextView info = listItemView.findViewById(R.id.info);
info.setText(book.getInfo());
TextView year = listItemView.findViewById(R.id.year_view);
year.setText(book.getYear());
return listItemView;
}
}
这是主要活动类
public class MainActivity extends AppCompatActivity {
private static final String LOG_TAG = MainActivity.class.getName();
private static final String GOOGLE_BOOK="https://www.googleapis.com/books/v1/volumes?q=science";
private BookAdapter bookAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bookAdapter = new BookAdapter(MainActivity.this, new ArrayList<Book>());
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(bookAdapter);
BookAsyncTask task = new BookAsyncTask();
task.execute(GOOGLE_BOOK);
}
private class BookAsyncTask extends AsyncTask<String, Void, List<Book>> {
@Override
protected List<Book> doInBackground(String... urls) {
if (urls.length < 1 | urls[0] == null) {
return null;
}
List<Book> data = QueryUtils.fetchBookData(urls[0]);
return data;
}
protected void OnPostExecute(List<Book> data) {
bookAdapter.clear();
// If there is a valid list of {@link Earthquake}s, then add them to the adapter's
// data set. This will trigger the ListView to update.
if (data != null && !data.isEmpty()) {
bookAdapter.addAll(data);
}
}
}
}
这是从Google图书中获取数据的util类
public class QueryUtils {
public QueryUtils(){
}
private static final String LOG_TAG = QueryUtils.class.getSimpleName();
public static List<Book> fetchBookData(String requestUrl){
URL url = createUrl(requestUrl);
String jsonResponse = null;
try{
jsonResponse = makeHttpUrl(url);
}catch(IOException e){
Log.e(LOG_TAG, "Error closing input stream", e);
}
List<Book> books = extractFeatureFromJson(jsonResponse);
return books;
}
private static URL createUrl(String requestUrl){
URL url = null;
try{
url = new URL(requestUrl);
}catch (MalformedURLException e){
Log.e(LOG_TAG, "Error with creating URL ", e);
}
return url;
}
private static String makeHttpUrl(URL url) throws IOException {
String jsonResponse = null;
if (url == null){
return jsonResponse;
}
InputStream inputStream = null;
HttpURLConnection urlConnection = null;
try{
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
if(urlConnection.getResponseCode()==200){
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
}else {
Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
}} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the Book JSON results.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
inputStream.close();
}
}
return jsonResponse;
}
private static 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();
}
private static ArrayList<Book> extractFeatureFromJson(String bookJson){
if (TextUtils.isEmpty((bookJson))){
return null;
}
ArrayList<Book> books = new ArrayList<>();
try {
JSONObject baseJsonObject = new JSONObject(bookJson);
JSONArray items = baseJsonObject.getJSONArray("items");
for(int i = 0;i < items.length();i++){
JSONObject bookItem = items.getJSONObject(i);
JSONObject volumeInfo = bookItem.getJSONObject("volumeInfo");
String title = volumeInfo.getString("title");
String [] authors = new String[]{};
JSONArray authorJsonArray = volumeInfo.optJSONArray("authors");
if(authorJsonArray!= null) {
ArrayList<String> authorList = new ArrayList<String>();
for (int j = 0; j < authorJsonArray.length(); j++) {
authorList.add(authorJsonArray.get(j).toString());
}
authors = authorList.toArray(new String[authorList.size()]);
}
String date = volumeInfo.getString("publishedDate");
JSONObject imageLink = volumeInfo.getJSONObject("imageLinks");
String image = imageLink.getString("thumbnail");
String infoLink = "";
if(volumeInfo.optString("infoLink")!=null)
infoLink = volumeInfo.optString("infoLink");
Book book = new Book(title,authors,infoLink,date,image);
books.add(book);
}
} catch (JSONException e) {
Log.e("QueryUtils", "Problem parsing the book JSON results", e);
}
return books;
}
}
这是主要活动布局,是列表视图
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</ListView>
这是列表项视图布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iamge_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/title_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BookElement"
tools:text="title"/>
<TextView
android:id="@+id/info_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BookElement"
tools:text="info"/>
<TextView
android:id="@+id/author_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BookElement"
tools:text="Authors"/>
<TextView
android:id="@+id/year_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BookElement"
tools:text="year"/>
</LinearLayout>
并记录日志信息
10-18 15:05:28.241 19667-19667/? I/zygote: Not late-enabling -Xcheck:jni (already on)
10-18 15:05:28.256 19667-19667/? W/zygote: Unexpected CPU variant for X86 using defaults: x86
10-18 15:05:28.286 19667-19674/? I/zygote: Debugger is no longer active
10-18 15:05:28.417 19667-19667/? I/InstantRun: starting instant run server: is main process
10-18 15:05:28.651 19667-19691/? D/NetworkSecurityConfig: No Network Security Config specified, using platform default
10-18 15:05:28.670 19667-19694/? D/OpenGLRenderer: HWUI GL Pipeline
10-18 15:05:28.941 19667-19694/? I/OpenGLRenderer: Initialized EGL, version 1.4
10-18 15:05:28.941 19667-19694/? D/OpenGLRenderer: Swap behavior 1
10-18 15:05:28.950 19667-19694/? W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
10-18 15:05:28.950 19667-19694/? D/OpenGLRenderer: Swap behavior 0
[ 10-18 15:05:29.059 1604: 1629 D/ ]
HostConnection::get() New Host Connection established 0x929ed300, tid 1629
[ 10-18 15:05:29.061 1604: 1629 W/ ]
Unrecognized GLES max version string in extensions: ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_dma_v1
10-18 15:05:29.093 19667-19694/? D/EGL_emulation: eglCreateContext: 0xa3cfe3a0: maj 2 min 0 rcv 2
10-18 15:05:29.383 19667-19694/com.example.android.booklisting D/EGL_emulation: eglMakeCurrent: 0xa3cfe3a0: ver 2 0 (tinfo 0xa392ab20)
10-18 15:05:29.453 19667-19667/com.example.android.booklisting I/Choreographer: Skipped 44 frames! The application may be doing too much work on its main thread.
10-18 15:05:29.538 19667-19694/com.example.android.booklisting D/EGL_emulation: eglMakeCurrent: 0xa3cfe3a0: ver 2 0 (tinfo 0xa392ab20)