2013-10-18 42 views
3

我坐着試着用Android做一些練習。我今天的要點是製作一個簡單的應用程序,它將下載數據(來自URL的圖像)並在佈局中的ImageView控件中顯示它們。我在網上看到了一些例子,並完成了我的應用程序。一切似乎都沒問題,但當我按下按鈕時,我開始工作,但失敗後顯示錯誤:NULL POINTER 9error reading file)。這裏是我的代碼:使用AsyncTask下載許多圖像並將它們發佈到ImageView

package com.example.htmlcontent; 

import java.io.BufferedInputStream; 

import java.io.InputStream; 
import java.net.URL; 
import java.util.ArrayList; 

import android.app.Activity; 

import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.drawable.BitmapDrawable; 
import android.graphics.drawable.Drawable; 

import android.os.AsyncTask; 
import android.os.Bundle; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 


    public class MainActivity extends Activity { 
     private ImageView mImageView; 
     private ImageView mImageView2; 
     public Button button; 
     public static ArrayList<Drawable> drawable; 

     public static String[] URLs = {"http://zitterman.com/wp-content/uploads/2013/07/19194927_1371972212.jpg","http://i.imgur.com/CQzlM.jpg"}; 

     /** Called when the activity is first created. */ 
     @Override 
     public void onCreate(Bundle savedInstanceState) { 

      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_main); 


      mImageView = (ImageView) findViewById(R.id.test_image); 
      mImageView2 = (ImageView) findViewById(R.id.test_image2); 
      button = (Button) findViewById(R.id.download1); 

      button.setOnClickListener(new OnClickListener() { 

       @Override 
       public void onClick(View v) { 

        new DownloadImage().execute(); 
       } 
      }); 
     } 


     /** 
     * Simple functin to set a Drawable to the image View 
     * @param drawable 
     */ 
     @SuppressWarnings("deprecation") 
     private void setImage() 
     { 
      if(drawable.get(0) == null) 
      { 
       System.out.println("DRAWABLE JEST NULL"); 
      } 
      mImageView.setBackgroundDrawable(drawable.get(0)); 
      mImageView2.setBackgroundDrawable(drawable.get(1)); 
     } 

     public class DownloadImage extends AsyncTask<Void, Void, Void> { 



      /** 
      * Called after the image has been downloaded 
      * -> this calls a function on the main thread again 
      */ 
      protected void onPostExecute(Drawable image) 
      { 
       setImage(); 
      } 
      protected void onPreExecute() 
      { 
       Log.i("333333", "Uruchamiam WATEK SCIAGANIA ASYNCTASKIEM PLIKU Z NETA"); 
      } 

      @Override 
      protected Void doInBackground(Void... params) { 

       downloadImage(); 
       return null; 
      } 
      /** 
      * Actually download the Image from the _url 
      * @param _url 
      * @return 
      */ 
      @SuppressWarnings("deprecation") 
      private void downloadImage() 
      { 
       //Prepare to download image 

       URL url;   

       InputStream in; 
       BufferedInputStream buf; 

       //BufferedInputStream buf; 
       for(int i = 0; i<URLs.length; i++) 
       { 
        try { 
        url = new URL(URLs[i]); 
        in = url.openStream(); 

        // Read the inputstream 
        buf = new BufferedInputStream(in); 

        // Convert the BufferedInputStream to a Bitmap 
        Bitmap bMap = BitmapFactory.decodeStream(buf); 
        if (in != null) { 
         in.close(); 
        } 
        if (buf != null) { 
         buf.close(); 
        } 

        drawable.add(new BitmapDrawable(bMap)); 

       } catch (Exception e) { 
        Log.e("Error reading file", e.toString()); 
       } 

       } 

      } 


     } 
    } 

和我的XML文件格式:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 

    <Button 
     android:id="@+id/download1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Button" /> 

<TextView 
    android:layout_width="102dp" 
    android:layout_height="wrap_content" 
    android:text="hello" /> 

    <ImageView 
     android:id="@+id/test_image" 
     android:layout_width="match_parent" 
     android:layout_height="200dp" 
     android:background="@drawable/ic_launcher" /> 
    <ImageView 
     android:id="@+id/test_image2" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:background="@drawable/ic_launcher" /> 

</LinearLayout> 

我已經爲你在代碼的ArrayList是繪製對象列表,請參閱。代碼沒有錯誤。只有那個NULL POINTER。

+0

在你的'catch'塊中發佈logcat請 –

+0

,執行'e.printStackTrace()'併發布logcat的輸出。 –

+0

我建議你使用https://github.com/nostra13/Android-Universal-Image-Loader它非常容易使用,並且會爲你處理幾乎所有的事情。 – JustDoingIt

回答

1

更改你的異步任務,

public class DownloadImage extends AsyncTask<Void, Void, ArrayList<Drawable>> { 



     /** 
     * Called after the image has been downloaded 
     * -> this calls a function on the main thread again 
     */ 
     protected void onPostExecute(ArrayList<Drawable> drawable) 
     { 
      setImage(drawable); 
     } 
     protected void onPreExecute() 
     { 
      Log.i("333333", "Uruchamiam WATEK SCIAGANIA ASYNCTASKIEM PLIKU Z NETA"); 
     } 

     @Override 
     protected ArrayList<Drawable> doInBackground(Void... params) { 

      downloadImage(); 
      return drawable; 
     } 




private void setImage(ArrayList<Drawable> drawable) 
    { 
     if(drawable.get(0) == null) 
     { 
      System.out.println("DRAWABLE JEST NULL"); 
     } 
     mImageView.setBackgroundDrawable(drawable.get(0)); 
     mImageView2.setBackgroundDrawable(drawable.get(1)); 
    } 
+0

好的,謝謝你的作品!但是,你能告訴我爲什麼它應該是這樣嗎?我明白我靜態發送數組到AsyncTask,所以第一個參數是無效的。沒有更新,所以它是無效的。爲什麼第三個參數不應該是void?並在doInBackground ...爲什麼有返回,如果我有靜態數組,並從另一個函數(downloadImage)完成?爲什麼setImage函數應該有這個參數,如果數組是靜態的? – Darek

4

我認爲這是因爲你忘記初始化drawable。更改爲:

public static ArrayList<Drawable> drawable = new ArrayList<Drawable>(); 

下一頁由於您的AsyncTask是<Void, Void, Void>。您的文章應該執行如下:

@Override 
    protected void onPostExecute(Void aVoid) { 
     setImage(); 
    } 

的泛型類型<A,B,C>對應的參數和返回類型的不同的充方法。你應該閱讀更多關於它在這裏:https://stackoverflow.com/a/6053673/827110

(爲了完整起見),你還需要在你的AndroidManifest.xml添加(只<application..之前)Internet權限:

<uses-permission android:name="android.permission.INTERNET" /> 
+0

是的,我已經忘記了;) – Darek

0

好吧,我已經正確的說出你的意思了。是的,我忘了在開始初始化這個ArrayList,但你比我快;)因此,

public class MainActivity extends Activity { 
     private ImageView mImageView; 
     private ImageView mImageView2; 
     public Button button; 
     public static ArrayList<Drawable> drawable = new ArrayList<Drawable>(); 

     public static String[] URLs = {"http://zitterman.com/wp-content/uploads/2013/07/19194927_1371972212.jpg","http://i.imgur.com/CQzlM.jpg"}; 

     /** Called when the activity is first created. */ 
     @Override 
     public void onCreate(Bundle savedInstanceState) { 

      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_main); 


      mImageView = (ImageView) findViewById(R.id.test_image); 
      mImageView2 = (ImageView) findViewById(R.id.test_image2); 
      button = (Button) findViewById(R.id.download1); 

      button.setOnClickListener(new OnClickListener() { 

       @Override 
       public void onClick(View v) { 

        new DownloadImage().execute(); 
       } 
      }); 
     } 


     /** 
     * Simple functin to set a Drawable to the image View 
     * @param drawable 
     */ 
     @SuppressWarnings("deprecation") 
     private void setImage(ArrayList<Drawable> drawable) 
     { 
      if(drawable.get(0) == null) 
      { 
       System.out.println("DRAWABLE JEST NULL"); 
      } 
      mImageView.setBackgroundDrawable(drawable.get(0)); 
      mImageView2.setBackgroundDrawable(drawable.get(1)); 
     } 

     public class DownloadImage extends AsyncTask<Void, Void, ArrayList<Drawable>> { 

      /** 
      * Called after the image has been downloaded 
      * -> this calls a function on the main thread again 
      */ 
      protected void onPostExecute(ArrayList<Drawable> drawable) 
      { 
       setImage(drawable); 
      } 
      protected void onPreExecute() 
      { 
       Log.i("333333", "Uruchamiam WATEK SCIAGANIA ASYNCTASKIEM PLIKU Z NETA"); 
      } 

      @Override 
      protected ArrayList<Drawable> doInBackground(Void... params) { 

       downloadImage(); 
       return null; 
      } 
      /** 
      * Actually download the Image from the _url 
      * @param _url 
      * @return 
      */ 
      @SuppressWarnings("deprecation") 
      private void downloadImage() 
      { 
       //Prepare to download image 

       URL url;   

       InputStream in; 
       BufferedInputStream buf; 

       //BufferedInputStream buf; 
       for(int i = 0; i<URLs.length; i++) 
       { 
        try { 
        url = new URL(URLs[i]); 
        in = url.openStream(); 

        // Read the inputstream 
        buf = new BufferedInputStream(in); 

        // Convert the BufferedInputStream to a Bitmap 
        Bitmap bMap = BitmapFactory.decodeStream(buf); 
        if (in != null) { 
         in.close(); 
        } 
        if (buf != null) { 
         buf.close(); 
        } 

        drawable.add(new BitmapDrawable(bMap)); 

       } catch (Exception e) { 
        Log.e("Error reading file", e.toString()); 
       } 

       } 

      } 


     } 
    } 

現在它試圖下載圖像時崩潰。我不明白爲什麼我應該把ArrayList作爲第三個參數....?爲什麼如果我聲明靜態數組存儲我的圖像? OnPostExecute它應該只調用將完成剩餘工作的函數。

+0

你應該編輯你的原始問題或發佈一個新的問題。發佈答案有誤導性,可能會讓你失望! –

+0

我已經更新了我的答案。一切都應該現在工作。我希望你已經將internet權限添加到你的android.manifest。 –

+0

在doInBackground方法中,您返回null,將其更改爲返回drawable,因爲無論您在doInbackground中返回什麼,它都會返回postexecute,並且您可以在async任務中不給參數的情況下使用它,因爲您的數組是靜態的,但是如果您給你參數,因爲你不會忘記返回doinbackground的結果,即drawable。 –

相關問題