2017-05-25 126 views
1

我試圖在列表視圖中加載圖像和視頻的縮略圖。當我製作縮略圖時,我提供了一個默認縮略圖,以便輕鬆完成任務,因此縮略圖製作和加載放置在不同的線程中。但問題是應用程序崩潰/退出。Android應用程序在加載線程時崩潰

public View getView(final int position, View convertView, ViewGroup parent) 
{ 

    File file=new File(String.valueOf(filenames[position])); 
    if(file.isDirectory()){ 
     img=R.drawable.folder; 
    } 

    else{ 
     img=getImage(filenames[position]); 
    } 




    ViewHolder viewHolder = null; 
    if (convertView == null) { 
     LayoutInflater inflator = LayoutInflater.from(getContext()); 
     convertView = inflator.inflate(R.layout.list_item, null); 
     viewHolder = new ViewHolder(); 
     viewHolder.tv = (TextView) convertView.findViewById(R.id.textView1); 
     viewHolder.cb = (CheckBox) convertView.findViewById(R.id.checkBox1); 
     viewHolder.iv= (ImageView)convertView.findViewById(R.id.imageView); 
     viewHolder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 

      @Override 
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       int getPosition = (Integer) buttonView.getTag(); // Here we get the position that we have set for the checkbox using setTag. 
       myList.get(getPosition).setSelected(buttonView.isChecked()); // Set the value of checkbox to maintain its state. 
      } 
     }); 
     convertView.setTag(viewHolder); 
     convertView.setTag(R.id.textView1, viewHolder.tv); 
     convertView.setTag(R.id.checkBox1, viewHolder.cb); 
     convertView.setTag(R.id.checkBox1, viewHolder.iv); 
    } 
    else { 
     viewHolder = (ViewHolder) convertView.getTag(); 
    } 
    viewHolder.iv.getLayoutParams().height = 80; 
    viewHolder.iv.getLayoutParams().width = 80; 
    viewHolder.cb.setTag(position); // This line is important. 

    final ViewHolder finalViewHolder = viewHolder; 


    Thread t2 = new Thread(){ 

     public void run(){ 
      if((String.valueOf(filenames[position])).contains(".jpeg")||String.valueOf(filenames[position]).contains(".jpg")||String.valueOf(filenames[position]).contains(".png")||String.valueOf(filenames[position]).contains(".bmp")||String.valueOf(filenames[position]).contains(".webp")||String.valueOf(filenames[position]).contains(".gif")){ 
       thumb = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(String.valueOf(filenames[position])), 64, 64); 
       finalViewHolder.iv.setImageBitmap(thumb); 
      } 
      else if((String.valueOf(filenames[position])).contains(".mp4")||String.valueOf(filenames[position]).contains(".mkv")||String.valueOf(filenames[position]).contains(".webm")||String.valueOf(filenames[position]).contains(".3gp")||String.valueOf(filenames[position]).contains(".3gpp")){ 
       thumb=ThumbnailUtils.createVideoThumbnail(filenames[position].getPath(), MediaStore.Video.Thumbnails.MINI_KIND); 
       finalViewHolder.iv.setImageBitmap(thumb); 
      } 
     } 
    }; 
      finalViewHolder.iv.setImageResource(img); 
      finalViewHolder.tv.setText(myList.get(position).getName()); 
      finalViewHolder.cb.setChecked(myList.get(position).isSelected()); 
t2.start(); 



    return convertView; 
} 

我曾嘗試另一種選擇是:

使兩個線程,一個提供默認的拇指和其他同上T2。 無效。

+0

你有沒有異常記錄? – litelite

+0

@litelite「:android.view.ViewRootImpl $ CalledFromWrongThreadException:只有創建視圖層次結構的原始線程可以觸及其視圖。」 –

+0

你的線程沒有創建視圖,所以Android禁止觸摸View。您需要將圖像帶回UI線程,然後在該線程中更改圖像。 ['AsyncTask'](https://developer.android.com/reference/android/os/AsyncTask.html)非常適合這一點。 – litelite

回答

1

我建議你看看這個問題,這是從互聯網上下載的圖像列表視圖成。但它應該適用於你正在做的事情。

當用圖像填充列表視圖時,還有更多的事情需要記住。 是的,你用AsyncTask運行圖片加載,但你也必須考慮當列表項目離開網站和工作仍在進行時會發生什麼。 看看asyncTask中有弱引用的答案,如果不再需要,可以取消操作。

此外todya還有像IonPicasso這樣的libraties爲你做。

Load asynchronous images in listView

0

在UI線程上運行。 希望這有助於你

runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      //Your code to run in GUI thread here 
     }//public void run() { 
}); 
1
private class SomeTask extends AsyncTask<URL, Integer, Long> { 
protected void doInBackground(String... str) { 
     //Do the background stuff here 
    } 

} 

protected void onProgressUpdate(Integer... progress) { 

} 

protected void onPostExecute(Long result) { 
    //Do the UI stuff here 
} 
}