2016-01-27 100 views
0

我创建了一个自定义TextView来显示它并显示图像。我必须下载图像,然后在textview上显示它们。所以我认为我可以通过AsyncTask课来完成我的工作。在doInBackground我下载并保存在内部存储器上(离线模式),并在onPostExecute我调用一个方法,显示textview上的图像。但它不起作用。我的意思不是显示图片,而是显示img标签。从AsyncTask更新UI

我也尝试从AsyncTask类的onPostExecute方法和它的RUNNING获得状态。这不奇怪吗?我认为这将是FINISHED。我错过了一些有关AsyncTask类的内容吗?

下面是addImages方法,在这里我找到的文本img标签和数据存储在一个List,并调用DownLoadImage类扩展AsyncTask

private boolean add(final Context context, final Spannable spannable) { 
    path = context.getFilesDir(); 

    Pattern refImgPattern = Pattern.compile("<img .+?\\/>"); 
    hasChanges = false; 

    refImgMatcher = refImgPattern.matcher(spannable); 
    while (refImgMatcher.find()) { 

    set = true; 
    for (ImageSpan span : spannable.getSpans(refImgMatcher.start(), refImgMatcher.end(), ImageSpan.class)) { 
      if (spannable.getSpanStart(span) >= refImgMatcher.start() 
         && spannable.getSpanEnd(span) <= refImgMatcher.end() 
         ) { 
       spannable.removeSpan(span); 
      } else { 
       set = false; 
       break; 
       } 
      } 

    String imageUrl = spannable.subSequence(refImgMatcher.start(0), refImgMatcher.end(0)).toString().trim(); 

    width = 0; 
    Pattern widthPattern = Pattern.compile("width=\"[0-9]+?\""); 
    Matcher widthMatcher = widthPattern.matcher(imageUrl); 

     if (widthMatcher.find()) { 
      String w = widthMatcher.group(0); 
      w = w.replaceAll("width=", ""); 
      w = w.replaceAll("\"", ""); 
      width = Integer.valueOf(w); 
     } 

      height = 0; 
      Pattern heightPattern = Pattern.compile("height=\"[0-9]+?\""); 
      Matcher heightMatcher = heightPattern.matcher(imageUrl); 

      if (heightMatcher.find()) { 
       String h = heightMatcher.group(0); 
       h = h.replaceAll("height=", ""); 
       h = h.replaceAll("\"", ""); 
       height = Integer.valueOf(h); 
      } 

    Pattern urlPattern = Pattern.compile("(http|ftp|https):\\/\\/([\\w_-]+(?:(?:\\.[\\w_ -]+)+))([\\w.,@?^=%&:\\/~+#-]*[\\[email protected]?^=%&\\/~+#-])?"); 
    Matcher urlMatcher = urlPattern.matcher(imageUrl); 

     if (urlMatcher.find()) 
      imageUrl = urlMatcher.group(0); 

      imageName = siteData.getId() + "_" + imageUrl.substring(imageUrl.lastIndexOf("/") + 1, imageUrl.length()); 

      images.add(new Image(imageUrl, imageName, width, height, refImgMatcher.start(0), refImgMatcher.end(0))); 


    } 

    if (images.size() > 0) { 

     for (final Image img : images) { 
      image = new File(path, img.name); 
      if (!image.exists()) { 
      new DownLoadImage(context, spannable, img).execute(); 
      } else 
       addImages(spannable, context, img); 
     } 
    } 

    return hasChanges; 
} 

这是addImages方法,其中,我替换图像

private void addImages(Spannable spannable, Context context, Image im) { 
     image = new File(path, im.name); 
     BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
     bitmap = BitmapFactory.decodeFile(image.getAbsolutePath(), bmOptions); 
     if (im.width > 0 && im.height > 0) 
      bitmap = Bitmap.createScaledBitmap(bitmap, im.width * 3, im.height * 3, true); 

     if (set) { 
      hasChanges = true; 
      spannable.setSpan(new ImageSpan(context, bitmap), 
        im.startIndex, 
        im.endIndex, 
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE 
      ); 
     } 

    } 

DownLoadImage

private class DownLoadImage extends AsyncTask<Void, Void, Void> { 

     private Connection connection = Connection.getInstance(); 
     private Context context; 
     private Spannable spannable; 
     private Image image; 

     public DownLoadImage(Context context, Spannable spannable, Image image) { 
      this.spannable = spannable; 
      this.context = context; 
      this.image = image; 
     } 

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

      try { 
       connection.openConnection(image.path, ConnectionType.GET, false, false, null); 

       Integer status = connection.getResponseCode(); 
       if (status >= 200 && status < 300) { 
        InputStream inputStream = new BufferedInputStream(connection.getInputStream()); 
        Bitmap bitmap = BitmapFactory.decodeStream(inputStream); 
        Actions.saveImage(context, bitmap, image.name); 
       } 

      } catch (IOException e) { 
       e.printStackTrace(); 
      } finally { 
       connection.closeConnection(); 
      } 


      return null; 
     } 

     @Override 
     protected void onPostExecute(Void aVoid) { 
      super.onPostExecute(aVoid); 
      Log.i("status", this.getStatus().toString()); 
      addImages(spannable, context, image); 
     } 
    } 

***** EDIT标签*****

getTextWithImages其中我称之为add方法

private Spannable getTextWithImages(Context context, CharSequence text) { 
    images = new ArrayList<>(); 

    Spannable spannable = spannableFactory.newSpannable(text); 
    add(context, spannable); 
    return spannable; 
} 

setText方法,我称之为getTextWithImages

@Override 
public void setText(CharSequence text, BufferType type) { 
    Spannable s = getTextWithImages(getContext(), text); 
    super.setText(s, BufferType.SPANNABLE); 
} 
+0

1.检查你的正则表达式是否正确。 2.只分析图像URL,让[Picasso](http://square.github.io/picasso/)或[Glide](https://github.com/bumptech/glide)完成剩下的工作。 – Emmanuel

+0

正则表达式是正确的,因为它适用于离线模式。我尝试过毕加索,但输出结果是一样的 –

+0

正则表达式是否会为您提供有效的URL?如果您在浏览器上访问该网址,是否显示该图片? – Emmanuel

回答

0

您可以创建可调用回调到UI线程的界面,而不是使用上下文。例如,在您的AsyncTask:

private class DownLoadImage extends AsyncTask<Void, Void, Void> { 
    private Connection connection = Connection.getInstance(); 
    private Context context; 
    private Spannable spannable; 
    private Image image; 
    private OnImageDownloadedListener mOnImageDownloadedListener; 
    ... 

    @Override 
    protected Void doInBackground(Void... params) { 
     ... 
     ... 
    } 
    // Interface the task will use to communicate with your activity method. 
    public interface OnImageDownloadedListener { 
     void onImageDownloaded(Spannable spannable, Image image); // No need for context. 
    } 

    @Override 
    protected void onPostExecute(Void aVoid) { 
     if (mOnImageDownloadedListener != null) { 
      // If we set a listener, invoke it. 
      mOnImageDownloadedListener.onImageDownloaded(spannable, image); 
     } 
    } 

    // Setter. 
    public setOnImageDownloadedListener(OnImageDownloadedListener listener) { 
     mOnImageDownloadedListener = listener; 
    } 
} 

然后,当你创建你的任务尝试:

if (!image.exists()) { 
    // Create the task. 
    DownloadImage downloadTask = new DownLoadImage(context, spannable, img); 

    // Set your listener. 
    downloadTask.setOnImageDownloadedListener(new OnImageLoadedListener() { 
     @Override 
     public void onImageDownloaded(Spannable spannable, Image image) { 
      // Add the images. 
      addImages(spannable, **YourContextHere(Activity/etc)**.this, image) 
     } 
    }); 

    // Execute. 
    downloadTask.execute(); 
} else 
    addImages(spannable, context, img); 

希望这有助于。

+0

不,它具有相同的输出。 :\ 看,我调试应用程序,发现当我下载图像并向他们显示hasChanges值(返回add方法的值)为false时,但是当我尝试从内部存储器显示它们时是true ... –

+0

hasChanges将始终从下载任务中为假,因为AsyncTask是异步的。当您调用execute()后台线程时,会创建与UI线程分开的后台线程,并在该后台线程中执行'doInBackground()'。 'execute()'是非阻塞的,意味着它将运行,然后立即继续下一行代码,无论'doInBackground()'中的代码是否完成。 –

+0

嗯,所以我怎么能使add方法返回true? :\ –