2011-06-10 26 views
13

Tôi có một cái nhìn hình ảnh, tôi đã viết swiping, tại thời điểm swiping, những hình ảnh được tải xuống từ Internet, vì vậy tôi nghĩ rằng tôi phải tải về các hình ảnh trong nền trước khi swiping, cho rằng tôi cần phải sử dụng asynctask hoặc Dịch vụ hoặc IntentService, tất cả những điều này sẽ giúp tải xuống và lưu trữ dữ liệu/dữ liệu/mypackages, nhưng vẫn vuốt chậm trong trường hợp của tôi, cũng truyền đạt cho tôi cái nào tốt nhất, là tôi đang gọi đúng cáchCần trợ giúp khi tải xuống trong hình nền trong Android?

1. AsyncTask

2. dịch vụ

3. Dịch vụ Ý định như hình dưới đây,

im nhầm lẫn đó là một phương pháp đúng bởi vì vẫn còn vấn đề của tôi không được giải quyết

Dưới đây là AsyncTask đoạn mã mẫu

public class Demo extends Activity { 

    @Override 

    public void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 

    setContentView(R.layout.main); 

     new FirstTask().execute(); // calling Asynctask here 

    } 

}

Mã tác vụ không đồng bộ

private class FirstTask extends AsyncTask<Void, Void, Void> { 
     private final ProgressDialog dialog = new ProgressDialog(Catalogue.this); 
     int temp = 0; 

     // can use UI thread here 
     protected void onPreExecute() { 
      this.dialog.setMessage("Loading..."); 
      this.dialog.setCancelable(false); 
      //this.dialog.show(); 
      System.gc(); 
      Toast.makeText(Catalogue.this, "My Async Created", 
        Toast.LENGTH_LONG).show(); 
     } 

     @Override 
     protected Void doInBackground(Void... params) { 
      Looper.prepare(); 
      try { 

       myddownloadmethod();// calling my download method 

      } catch (Exception e) { 
       Util.trace("Error in Async"+e.getMessage()); 

      } 
       Looper.loop(); 

      return null; 
     } 

     protected void onPostExecute(Void result) { 

      if (this.dialog.isShowing()) { 
       Toast.makeText(Catalogue.this, "My Async destroyed", 
         Toast.LENGTH_LONG).show(); 
       Toast.makeText(Catalogue.this, "count" + temp, 
         Toast.LENGTH_LONG).show(); 
       this.dialog.dismiss(); 
      } 
     } 
    } 

Đây là dịch vụ My sinppet

public class MyService extends Service implements Runnable 

{  @Override 

     public void onCreate() { 

       super.onCreate(); 

       Thread mythread = new Thread(this); 

       mythread.start(); 

     } 



     public void run() { 

       Looper.prepare(); 

       try { 

         myddownloadmethod();// calling my download method 

       } catch (Exception e1) { 

         // TODO Auto-generated catch block 

         e1.printStackTrace(); 

       } 

       Looper.loop(); 

     } 



     @Override 
     public IBinder onBind(Intent intent) { 

       // TODO Auto-generated method stub 

       return null; 

     } 



} 



Invoking Service 

public class ServicesDemo extends Activity {  

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

     startService(new Intent(this, MyService.class)); 


    } 

} 

Dưới đây là IntentService Mã

public class Downloader extends IntentService { 

    public Downloader() { 
     super("Downloader"); 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 


    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 

      } 

    @Override 
    public void onHandleIntent(Intent i) { 

     try { 
      myddownloadmethod();// calling my download method 
     } catch (Exception e1) { 
      // TODO Auto-generated catch block 
      Log.d("Error",e1.getMessage()); 
     } 

    } 
} 

Calling IntentService từ MyActivity

public class ServicesDemo extends Activity {  
     @Override 
     public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     Intent i1=new Intent(this, Downloader.class); 
     startService(i1); 



     } 

    } 
+0

Looper.prepare(); trong doInBackground tại sao? trông giống như lỗi thiết kế – Selvin

+0

@selvin: tôi có ngoại lệ này, Không thể tạo trình xử lý bên trong chuỗi chưa được gọi là Looper.prepare(), đó là lý do tại sao tôi đã sử dụng –

+3

heh ** không sử dụng chuỗi giao diện người dùng trong doInBackground ** .. Sử dụng publishProgress và ghi đè onProgressUpdate và trong phương pháp này làm somtheting trên UI thread ... thats cách AsyncTask hoạt động ... – Selvin

Trả lời

2

Bạn đang có lẽ trên kỹ thuật này. Tôi đã thực hiện swiping với tự động tải hình ảnh và tôi chỉ là một sử dụng một lớp tiện ích đơn giản mà nó tất cả cho tôi thông qua gọi phương thức tĩnh. Hãy thử lớp này:

package com.beget.consumer.util; 

/* 
Licensed to the Apache Software Foundation (ASF) under one 
or more contributor license agreements. See the NOTICE file 
distributed with this work for additional information 
regarding copyright ownership. The ASF licenses this file 
to you under the Apache License, Version 2.0 (the 
"License"); you may not use this file except in compliance 
with the License. You may obtain a copy of the License at 

http://www.apache.org/licenses/LICENSE-2.0 

Unless required by applicable law or agreed to in writing, 
software distributed under the License is distributed on an 
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express or implied. See the License for the 
specific language governing permissions and limitations 
under the License.  
*/ 
import java.io.IOException; 
import java.io.InputStream; 
import java.lang.ref.WeakReference; 
import java.net.MalformedURLException; 
import java.util.HashMap; 
import java.util.Map; 

import org.apache.http.HttpResponse; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.DefaultHttpClient; 

import android.graphics.drawable.Drawable; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.widget.ImageView; 

public class DrawableLoader { 
    private final Map<String, Drawable> drawableMap; 
    private WeakReference<ImageView> imageViewReference; 

    public DrawableLoader() { 
     drawableMap = new HashMap<String, Drawable>(); 
    } 

    public Drawable fetchDrawable(String urlString) { 
     if (drawableMap.containsKey(urlString)) { 
      return drawableMap.get(urlString); 
     } 

     Log.d(this.getClass().getSimpleName(), "image url:" + urlString); 
     try { 
      InputStream is = fetch(urlString); 
      Drawable drawable = Drawable.createFromStream(is, "src"); 
      drawableMap.put(urlString, drawable); 
      Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", " 
        + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", " 
        + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth()); 
      return drawable; 
     } catch (MalformedURLException e) { 
      Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); 
      return null; 
     } catch (IOException e) { 
      Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); 
      return null; 
     } 
    } 

    public void fetchDrawableOnThread(final String urlString, final ImageView imageView) { 

     imageViewReference = new WeakReference<ImageView>(imageView); 

     if (drawableMap.containsKey(urlString)) { 
      imageViewReference.get().setImageDrawable(drawableMap.get(urlString)); 
     } 

     final Handler handler = new Handler() { 
      @Override 
      public void handleMessage(Message message) { 
       imageViewReference.get().setImageDrawable((Drawable) message.obj); 
      } 
     }; 

     Thread thread = new Thread() { 
      @Override 
      public void run() { 
       //TODO : set imageView to a "pending" image 
       Drawable drawable = fetchDrawable(urlString); 
       Message message = handler.obtainMessage(1, drawable); 
       handler.sendMessage(message); 
      } 
     }; 
     thread.start(); 
    } 

    private InputStream fetch(String urlString) throws MalformedURLException, IOException { 
     DefaultHttpClient httpClient = new DefaultHttpClient(); 
     HttpGet request = new HttpGet(urlString); 
     HttpResponse response = httpClient.execute(request); 
     return response.getEntity().getContent(); 
    } 

} 

Đây là tất cả những gì bạn cần. Sau đó, khi bạn cần tải hình ảnh, bạn gọi:

fetchDrawableOnThread("http://path/to/your/image.jpg", yourImageViewReference); 

Vậy đó.
Nếu bạn có một URL từ một đối tượng JSON, phân tích cú pháp URL vào chuỗi của bạn vậy:
String url = jsonObj.getString("url"); Sau đó gọi fetchDrawableOnThread(url, yourImageViewReference);

+0

tôi không thể làm điều này, bởi vì tất cả các url là các url động được phân tích cú pháp từ một JSON –

+0

Như của tôi. Phân tích cú pháp URL từ JSON của bạn thành một biến và sau đó thay thế thông số đầu tiên của chuỗi bằng biến của bạn. –

+0

Cuối trò chơi, nhưng điều gì sẽ xảy ra khi ứng dụng của bạn được xoay vòng. Nó sẽ không bị giết sao? – MollyCat

16

Cách tốt nhất để tải nó bằng cách sử dụng dịch vụ như tôi đã làm để tải về các tập tin từ máy chủ và đưa vào thẻ SD cũng sử dụng thông báo cho nó. Đó là mã khá dài nhưng tôi nghĩ rằng mã hoàn hảo, nếu không hiểu bất kỳ điều gì thì hãy truy cập blog nhà phát triển Android cho các dịch vụ.

public class DownloadService extends Service{ 

    SharedPreferences preferences; 

    private static final String DOCUMENT_VIEW_STATE_PREFERENCES = "DjvuDocumentViewState"; 

     private Looper mServiceLooper; 
     private ServiceHandler mServiceHandler; 
     private NotificationManager mNM; 
     String downloadUrl; 
     public static boolean serviceState=false; 

     // Handler that receives messages from the thread 
     private final class ServiceHandler extends Handler { 
      public ServiceHandler(Looper looper) { 
       super(looper); 
      } 
      @Override 
      public void handleMessage(Message msg) { 
       downloadFile(); 
       showNotification(getResources().getString(R.string.notification_catalog_downloaded),"VVS"); 
       stopSelf(msg.arg1); 
      } 
     } 


    @Override 
     public void onCreate() { 
      serviceState=true; 
      mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 
      HandlerThread thread = new HandlerThread("ServiceStartArguments",1); 
      thread.start(); 

      // Get the HandlerThread's Looper and use it for our Handler 
      mServiceLooper = thread.getLooper(); 
      mServiceHandler = new ServiceHandler(mServiceLooper); 

     } 



    @Override 
     public int onStartCommand(Intent intent, int flags, int startId) { 
      Log.d("SERVICE-ONCOMMAND","onStartCommand"); 

       Bundle extra = intent.getExtras(); 
       if(extra != null){ 
        String downloadUrl = extra.getString("downloadUrl"); 
        Log.d("URL",downloadUrl); 

        this.downloadUrl=downloadUrl; 
       } 

       Message msg = mServiceHandler.obtainMessage(); 
       msg.arg1 = startId; 
       mServiceHandler.sendMessage(msg); 

       // If we get killed, after returning from here, restart 
       return START_STICKY; 
      } 



    @Override 
      public void onDestroy() { 

      Log.d("SERVICE-DESTROY","DESTORY"); 
      serviceState=false; 
      //Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); 
      } 


    @Override 
     public IBinder onBind(Intent intent) { 
      // We don't provide binding, so return null 
      return null; 
     } 


     public void downloadFile(){ 

      downloadFile(this.downloadUrl,fileName); 


     } 



     void showNotification(String message,String title) { 
     // In this sample, we'll use the same text for the ticker and the expanded notification 
     CharSequence text = message; 

     // Set the icon, scrolling text and timestamp 
     Notification notification = new Notification(R.drawable.icon, "vvs", 
       System.currentTimeMillis()); 
     notification.flags |= Notification.FLAG_AUTO_CANCEL; 
     Intent intent = new Intent(this, HomeScreenActivity.class); 
     intent.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP); 
     //The PendingIntent to launch our activity if the user selects this notification 
     PendingIntent contentIntent = PendingIntent.getActivity(this.getBaseContext(), 0, 
       intent, PendingIntent.FLAG_CANCEL_CURRENT); 

     // Set the info for the views that show in the notification panel. 
     notification.setLatestEventInfo(this, title, 
         text, contentIntent); 
     // Send the notification. 
     // We use a layout id because it is a unique number. We use it later to cancel. 
     mNM.notify(R.string.app_name, notification); 
    } 

    public void downloadFile(String fileURL, String fileName) { 

    StatFs stat_fs = new StatFs(Environment.getExternalStorageDirectory().getPath()); 
    double avail_sd_space = (double)stat_fs.getAvailableBlocks() *(double)stat_fs.getBlockSize(); 
    //double GB_Available = (avail_sd_space/1073741824); 
    double MB_Available = (avail_sd_space/10485783); 
    //System.out.println("Available MB : " + MB_Available); 
    Log.d("MB",""+MB_Available); 
    try { 
     File root =new File(Environment.getExternalStorageDirectory()+"/vvveksperten"); 
     if(root.exists() && root.isDirectory()) { 

     }else{ 
      root.mkdir(); 
     } 
     Log.d("CURRENT PATH",root.getPath()); 
     URL u = new URL(fileURL); 
     HttpURLConnection c = (HttpURLConnection) u.openConnection(); 
     c.setRequestMethod("GET"); 
     c.setDoOutput(true); 
     c.connect(); 
      int fileSize = c.getContentLength()/1048576; 
      Log.d("FILESIZE",""+fileSize); 
      if(MB_Available <= fileSize){ 
       this.showNotification(getResources().getString(R.string.notification_no_memory),getResources().getString(R.string.notification_error)); 
       c.disconnect(); 
       return; 
      } 

     FileOutputStream f = new FileOutputStream(new File(root.getPath(), fileName)); 

     InputStream in = c.getInputStream(); 


     byte[] buffer = new byte[1024]; 
     int len1 = 0; 
     while ((len1 = in.read(buffer)) > 0) { 
      f.write(buffer, 0, len1); 
     } 
     f.close(); 
     File file = new File(root.getAbsolutePath() + "/" + "some.pdf"); 
     if(file.exists()){ 
      file.delete(); 
      Log.d("FILE-DELETE","YES"); 
     }else{ 
      Log.d("FILE-DELETE","NO"); 
     } 
     File from =new File(root.getAbsolutePath() + "/" + fileName); 
     File to = new File(root.getAbsolutePath() + "/" + "some.pdf"); 


     } catch (Exception e) { 
     Log.d("Downloader", e.getMessage()); 

    } 
+0

Tôi thích giải pháp này, tuy nhiên có an toàn không để cho HandlerThread chạy mà không bao giờ gọi phương thức quit() hoặc quitSafely()? Hay liệu HandlerThread có tự động tự động sau một thời gian không? Tôi không biết cũng không tìm thấy bất cứ nơi nào vòng đời của một đối tượng như vậy. – TheYann

+3

là nó hoạt động khi ứng dụng bị giết? –

3

Đối với bất cứ ai chạy vào câu hỏi này sau, hãy nhìn vào cơ chế async tải sử dụng trong mã mẫu android cho dự án com.example.android.bitmapfun.ui.ImageGridActivity. Nó tải hình ảnh một cách không đồng bộ và cũng lưu trữ chúng để hiển thị ngoại tuyến trong một ImageView.Folks đã gói mã của họ xung quanh này và làm thư viện tải hình ảnh of their own. Các thư viện này sử dụng AsyncTask thay vì một dịch vụ. Tác vụ không đồng bộ được dự kiến ​​sẽ kết thúc công việc của họ trong vòng vài giây.

Nếu bạn đang tìm cách tải xuống thứ gì đó lớn hơn, tôi khuyên bạn nên sử dụng DownloadManager vì API 9 thay vì sử dụng dịch vụ. Có rất nhiều mã trong đó có thêm khả năng phục hồi để tải xuống.

Trình quản lý tải xuống là dịch vụ hệ thống xử lý tải xuống HTTP trong thời gian dài. Khách hàng có thể yêu cầu một URI được tải xuống một tệp đích cụ thể. Trình quản lý tải xuống sẽ tiến hành tải xuống dưới nền, xử lý các tương tác HTTP và thử tải lại sau khi lỗi hoặc thay đổi kết nối và khởi động lại hệ thống. Các cá thể của lớp này sẽ được lấy thông qua getSystemService (String) bằng cách truyền DOWNLOAD_SERVICE. Các ứng dụng yêu cầu tải xuống thông qua API này phải đăng ký bộ thu phát sóng cho ACTION_NOTIFICATION_CLICKED để xử lý thích hợp khi người dùng nhấp vào tải xuống đang chạy trong thông báo hoặc từ giao diện người dùng tải xuống. Lưu ý rằng ứng dụng phải có quyền INTERNET để sử dụng lớp này.

+0

Tôi nghĩ rất nhiều người sẽ muốn thứ gì đó mạnh mẽ hơn UIL. UIL cũng yêu cầu ghi dữ liệu vào bộ nhớ ngoài. Trình quản lý tải xuống cũng tuyệt vời nhưng tương tự yêu cầu dữ liệu phải được ghi vào vị trí thứ hai và sau đó được sao chép vào ứng dụng của bạn. – dcow

Các vấn đề liên quan