2017-05-25 115 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 
} 
}