Загрузка нескольких изображений на сервер в очереди

Случай использования: загрузка изображений в очередь в фоновом режиме на сервер, изображения могут быть веб-адресами или файлами изображений, хранящимися в памяти телефона.

То, что я хочу Ограничить количество элементов в очереди до 3 и показать размытые изображения в качестве заполнителей для фактических изображений, загружаемых в recyclerview, в действие с индикатором выполнения на каждом заполнителе, указывающем, сколько из них было загружено. В верхней части каждого заполнителя находятся три кнопки для приостановки, отмены или возобновления загрузки изображения.

Текущая ситуация: прямо сейчас я использовал Multipart в Retrofit 1.9.0 для загрузки изображений, и этот вызов службы выполнялся внутри этой операции.

Я не могу понять, как отменить, приостановить или возобновить запрос multipart-POST с помощью Retrofit или любой другой библиотеки в целом и как связать событие пользовательского интерфейса с потоком службы api. Я могу обновить интерфейс пользователя из службы, но как мне что-то обновить в сервисе от события в пользовательском интерфейсе (pause / resume / cancel)?

Как следует использовать этот вариант использования? Нужно ли использовать сервис? Могу ли я показывать индикаторы прогресса в другом действии на основе запросов, выполняемых в службе? Какая должна быть архитектура для этого процесса? Мне не нужен код для этого, но если есть некоторые полезные ссылки, связанные с этим, я хотел бы прочитать и протестировать его, чтобы, наконец, получить мой подход.

Solutions Collecting From Web of "Загрузка нескольких изображений на сервер в очереди"

Вот как вы можете это сделать: это пример кода для загрузки изображения с устройства путем передачи пути изображения. Аналогично, вы можете сделать это для URL-адреса изображения. Шаги: 1) Создайте поток, который будет запускаться для каждого изображения. 2) после этого каждая загрузка изображения даст вам ответ. 3) теперь для каждого изображения вы можете обновить свой интерфейс.

 //TODO: Multiple file upload public class FileUpload implements Runnable { Context context; String uploadApiUrl, uploadFilePath, fileType; int uploadId; LocalQueenDataBase localQueenDataBase; Activity activity; public FileUpload(Context context, ,String uploadApiUrl, String uploadFilePath, String fileType, int uploadId) { this.context = context; this.uploadApiUrl = uploadApiUrl; this.uploadFilePath = uploadFilePath; this.fileType = fileType; this.uploadId = uploadId; localQueenDataBase = new LocalQueenDataBase(context); Thread uploader = new Thread(this); uploader.start(); } @Override public void run() { try { executeMultipartPost(); } catch (Exception e) { e.printStackTrace(); } } public void executeMultipartPost() throws Exception { try { String originalPath = uploadFilePath; if (uploadFilePath == null) { uploadFilePath = originalPath; } HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("your api url"); httppost.addHeader("put your header if required") FileBody bin = new FileBody(new File(uploadFilePath)); StringBody fileTypeBody = new StringBody(fileType); StringBody uploadIdBody = new StringBody(uploadId + ""); MultipartEntity reqEntity = new MultipartEntity(); reqEntity.addPart("file", bin); reqEntity.addPart("fileType", fileTypeBody); reqEntity.addPart("uploadId", uploadIdBody); httppost.setEntity(reqEntity); HttpResponse response = httpclient.execute(httppost); HttpEntity resEntity = response.getEntity(); String retSrc = EntityUtils.toString(resEntity);//Render your response //TODO: update your UI for each uploaded image by creating the Handler Message msg = handler.obtainMessage(); handler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); } } } final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { try { uploadGalleryRecyclerAdapter = new UploadGalleryRecyclerAdapter(getApplicationContext(), PostUpdateActivity.this, localQueenDataBase.getGallery()); postUpdateRV.setAdapter(uploadGalleryRecyclerAdapter); if (localQueenDataBase.getGallery().size() > 3) gallerylayoutManager.scrollToPosition(localQueenDataBase.getGallery().size() - 2); } catch (Exception e) { e.printStackTrace(); } super.handleMessage(msg); } }; 

Надеюсь, что это поможет вам.

Я настоятельно рекомендую вам использовать Square's Tape, когда вы загружаете сразу несколько файлов / изображений, глядя на простоту использования, эффективность, обработку ошибок, систему очередей. Если вы используете только один файл во время, попробуйте использовать любую загрузку файлов из нескольких частей в любых клиентах Http для Android

Это то, что квадратная лента:

Лента представляет собой набор связанных с очередью классов для Android и Java by Square, Inc.

QueueFile – это быстрый, транзакционный, основанный на файлах FIFO. Добавление и удаление из экземпляра является операцией O (1) и является атомарной. Писания синхронны; Данные будут записаны на диск до возвращения операции. Основной файл структурирован, чтобы выжить и даже системные сбои, и если исключение ввода-вывода выбрано во время мутирующего изменения, это изменение отменяется.

ObjectQueue представляет собой упорядочение произвольных объектов, которые могут поддерживаться либо файловой системой (через QueueFile), либо только в памяти.

TaskQueue – это специальная очередь объектов, которая содержит задачи, объекты, которые имеют представление о выполнении. Экземпляры управляются внешним исполнителем, который готовит и выполняет заданные задачи.

 enter codepackage com.mohit.mom.multipleimage; import android.annotation.SuppressLint; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.os.StrictMode; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.GridView; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.ByteArrayBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import java.io.ByteArrayOutputStream; import java.util.ArrayList; @SuppressLint("NewApi") public class MainActivity extends Activity { private Button upload, pick; private ProgressDialog dialog; MultipartEntity entity; GridView gv; int count = 0; public ArrayList<String> map = new ArrayList<String>(); Bundle b; TextView noImage; HttpEntity resEntity; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() .permitAll().build(); StrictMode.setThreadPolicy(policy); b = getIntent().getExtras(); noImage = (TextView) findViewById(R.id.noImage); upload = (Button) findViewById(R.id.btnUpload); pick = (Button) findViewById(R.id.btnPicture); gv = (GridView) findViewById(R.id.gridview); gv.setAdapter(new ImageAdapter(this)); if (b != null) { ArrayList<String> ImgData = b.getStringArrayList("IMAGE"); for (int i = 0; i < ImgData.size(); i++) { map.add(ImgData.get(i).toString()); } } else { noImage.setVisibility(View.VISIBLE); } upload.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { new ImageUploadTask().execute(count + "", "pk" + count + ".jpg"); } }); pick.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Intent i3 = new Intent(MainActivity.this, UploadActivity.class); startActivity(i3); } }); } class ImageUploadTask extends AsyncTask<String, Void, String> { String sResponse = null; @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); dialog = ProgressDialog.show(MainActivity.this, "Uploading", "Please wait...", true); dialog.show(); } @Override protected String doInBackground(String... params) { try { String url = "yours url"; int i = Integer.parseInt(params[0]); Bitmap bitmap = decodeFile(map.get(i)); HttpClient httpClient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); HttpPost httpPost = new HttpPost(url); entity = new MultipartEntity(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); bitmap.compress(CompressFormat.JPEG, 50, bos); byte[] data = bos.toByteArray(); entity.addPart("user_id", new StringBody("199")); entity.addPart("club_id", new StringBody("10")); entity.addPart("club_image", new ByteArrayBody(data, "image/jpeg", params[1])); httpPost.setEntity(entity); HttpResponse response = httpClient.execute(httpPost); resEntity = response.getEntity(); sResponse = EntityUtils.toString(resEntity); //HttpResponse response = httpClient.execute(httpPost,localContext); //sResponse = EntityUtils.getContentCharSet(response.getEntity()); System.out.println("sResponse : " + sResponse); } catch (Exception e) { if (dialog.isShowing()) dialog.dismiss(); Log.e(e.getClass().getName(), e.getMessage(), e); } return sResponse; } @Override protected void onPostExecute(String sResponse) { try { if (dialog.isShowing()) dialog.dismiss(); if (sResponse != null) { Toast.makeText(getApplicationContext(), sResponse + " Photo uploaded successfully", Toast.LENGTH_SHORT).show(); count++; if (count < map.size()) { new ImageUploadTask().execute(count + "", "hm" + count + ".jpg"); } } } catch (Exception e) { Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); Log.e(e.getClass().getName(), e.getMessage(), e); } } } public Bitmap decodeFile(String filePath) { // Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, o); // The new size we want to scale to final int REQUIRED_SIZE = 1024; // Find the correct scale value. It should be the power of 2. int width_tmp = o.outWidth, height_tmp = o.outHeight; int scale = 1; while (true) { if (width_tmp < REQUIRED_SIZE && height_tmp < REQUIRED_SIZE) break; width_tmp /= 2; height_tmp /= 2; scale *= 2; } BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; Bitmap bitmap = BitmapFactory.decodeFile(filePath, o2); return bitmap; } private class ImageAdapter extends BaseAdapter { private Context mContext; public ImageAdapter(Context c) { mContext = c; } public int getCount() { return map.size(); } public Object getItem(int position) { return null; } // create a new ImageView for each item referenced by the Adapter public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { // if it's not recycled, initialize some // attributes imageView = new ImageView(mContext); imageView.setLayoutParams(new GridView.LayoutParams(85, 85, Gravity.CENTER)); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setPadding(1, 1, 1, 1); } else { imageView = (ImageView) convertView; } //Bitmap bm=BitmapFactory.decodeFile(map.get(position)); final BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 8; Bitmap bmp = BitmapFactory.decodeFile(map.get(position),options); imageView.setImageBitmap(bmp); return imageView; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } } @Override public void onBackPressed() { // TODO Auto-generated method stub super.onBackPressed(); MainActivity.this.finish(); } }