Противоречивое поведение при загрузке изображений с использованием asynctask
-
28-09-2019 - |
Вопрос
То, что делает приложение, очень просто. Он загружает два RSS -канала и на каждом канале RSS он содержит два элемента с заголовком, изображением и ссылкой. А потом он загружает изображения, сохраняет их в локальную папку и отображает их. Итак, два RSS -канала и 4 изображения загрузки.
Я использую Asynctask для этого. Таким образом, два объекта Asynctasks вызываются для загрузки двух RSS -каналов и 4 Asynctasks для загрузки 4 изображений. Проблемы возникают, когда он пытается загрузить изображения. Для первого запуска он работает нормально. Но если я продолжаю перезагружать их, иногда Asynctask ничего не делает. И иногда это не может читать inputstream ... очень странно.
Есть ли какое -либо правило, которое мне не хватает для использования Asynctask?
Ниже приведены фрагменты моего кода.
public class TunesAppsWidgetProvider extends AppWidgetProvider {
private Intent taService = null;
private static boolean widgetEnabled = false;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
taService = new Intent(context, UpdateService.class);
context.startService(taService);
}
public static class UpdateService extends Service {
@Override
public void onStart(Intent intent, int startId) {
Log.d(Constants.TAG, "Service: onStart()");
Context context = getApplicationContext();
mViews = new RemoteViews(context.getPackageName(), R.layout.tunesappswidget);
thisWidget = new ComponentName(this, TunesAppsWidgetProvider.class);
manager = AppWidgetManager.getInstance(this);
buildFeedUpdate();
this.stopSelf();
Log.d(Constants.TAG, "Stop Service");
}
public void buildFeedUpdate() {
Log.d(Constants.TAG, "buildFeedUpdate");
Context context = getApplicationContext();
feedParser_0 = new FeedParser(context, Constants.FEED_ID_0);
feedParser_1 = new FeedParser(context, Constants.FEED_ID_1);
feedTask_0 = new LoadFeedTask();
feedTask_0.execute(
new LoadFeedTask.Payload(
feedParser_0,
UpdateService.this
)
);
feedTask_1 = new LoadFeedTask();
feedTask_1.execute(
new LoadFeedTask.Payload(
feedParser_1,
UpdateService.this
)
);
}
public void buildCoverUpdate(byte feedID, List<Message> feedRSS, String operator) {
Context context = getApplicationContext();
Log.d(Constants.TAG, "buildCoverUpdate: " + feedID);
try {
switch(feedID) {
case Constants.FEED_ID_0:
coverImage_0 = new CoverImage(context, feedRSS.get(Constants.ITEM_IDX_0).getImageLink(), Constants.SLOT_0);
coverImageTask_0 = new LoadCoverImageTask();
coverImageTask_0.execute(
new LoadCoverImageTask.Payload(
coverImage_0,
UpdateService.this
)
);
coverImage_1 = new CoverImage(context, feedRSS.get(Constants.ITEM_IDX_1).getImageLink(), Constants.SLOT_1);
coverImageTask_1 = new LoadCoverImageTask();
coverImageTask_1.execute(
new LoadCoverImageTask.Payload(
coverImage_1,
UpdateService.this
)
);
break;
case Constants.FEED_ID_1:
coverImage_2 = new CoverImage(context, feedRSS.get(Constants.ITEM_IDX_0).getImageLink(), Constants.SLOT_2, operator);
coverImageTask_2 = new LoadCoverImageTask();
coverImageTask_2.execute(
new LoadCoverImageTask.Payload(
coverImage_2,
UpdateService.this
)
);
coverImage_3 = new CoverImage(context, feedRSS.get(Constants.ITEM_IDX_1).getImageLink(), Constants.SLOT_3, operator);
bm_3 = coverImage_3.getDefaultCoverImage();
coverImageTask_3 = new LoadCoverImageTask();
coverImageTask_3.execute(
new LoadCoverImageTask.Payload(
coverImage_3,
UpdateService.this
)
);
break;
default:
break;
}
}
catch(Exception e) {
Log.d(Constants.TAG, "buildCoverUpdate: " + e.toString());
}
}
}
А ниже код для загрузки изображения. Иногда этот Doinbackground никогда не называется, хотя называется «исполнение». Иногда он застрял на растровом растровом растровом месте = Bitmapfactory.decodestream (in) 'здесь и никогда не сбежатся.
protected LoadCoverImageTask.Payload doInBackground(LoadCoverImageTask.Payload... param) {
HttpURLConnection httpConn = null;
InputStream in;
File imageFile;
FileOutputStream fos;
int slotIdx = param[0].coverImage.getSlotIndex();
System.setProperty("http.keepAlive", "false");
try{
URL fileURL = new URL(param[0].coverImage.getFileURL());
httpConn = (HttpURLConnection) fileURL.openConnection();
Log.d(Constants.TAG , "openConn: Slot " + slotIdx);
httpConn.setConnectTimeout(10000);
if(httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
Log.d(Constants.TAG , "200OK: Slot " + slotIdx + ": " + fileURL.toString());
in = httpConn.getInputStream();
imageFile = new File(param[0].coverImage.getFullFilePath());
fos = new FileOutputStream(imageFile);
try {
Bitmap bitmap = BitmapFactory.decodeStream(in);
Log.d(Constants.TAG , "200OK: Slot " + slotIdx + " decodeStream(in);");
if(bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos) == true) {
fos.flush();
fos.close();
in.close();
Log.d(Constants.TAG , "200OK-decodeOK: Slot " + slotIdx);
param[0].result = Constants.TRUE;
}
else {
fos.flush();
fos.close();
in.close();
Log.d(Constants.TAG , "200OK-decodeFail: Slot " + slotIdx);
param[0].result = Constants.FALSE;
}
}
catch(NullPointerException e) {
Log.d(Constants.TAG , "Slot " + slotIdx + ":" + e.toString());
param[0].result = Constants.RETRY;
}
}
else {
Log.d(Constants.TAG , "Slot " + slotIdx + ":" + httpConn.getResponseCode());
param[0].result = Constants.FALSE;
}
} catch(SocketTimeoutException e) {
Log.d(Constants.TAG , "Time Out: " + slotIdx + ":" + e.toString());
} catch(Exception e) {
Log.d(Constants.TAG , "Slot " + slotIdx + ":" + e.toString());
param[0].result = Constants.FALSE;
}
finally {
if(httpConn != null) httpConn.disconnect();
Log.d(Constants.TAG , "Slot " + slotIdx + ":httpConn.disconnect");
}
return param[0];
}
Я застрял на этом на пару дней. Пожалуйста, помогите ...
Решение
Может быть, проблема не в вашем коде. В BitmapFactory есть ошибка, и если вы используете Inputstream из HTTP-соединения, иногда он не загружает изображение хорошо.
смотреть на http://code.google.com/p/android/issues/detail?id=6066 за дополнительной информацией
Простое решение, которое работает для меня, - это загрузка данных целого контента в буфер, а затем использование метода Bitmapfactory.decodebytearray:
InputStream is = httpCon.getInputStream();
byte [] content = inputStreamToByteArray2(is);
image = BitmapFactory.decodeByteArray(content, 0, content.length);
public static final byte[] inputStreamToByteArray(InputStream is) throws IOException {
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int result = bis.read();
while(result !=-1) {
byte b = (byte)result;
buf.write(b);
result = bis.read();
}
return buf.toByteArray();
}
Или если вы не хотите читать на 1 байт:
public static final byte[] inputStreamToByteArray(InputStream is) throws IOException {
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
byte[] buffer = new byte[256];
int result = bis.read(buffer);
while(result > 0) {
buf.write(buffer, 0, result);
result = bis.read(buffer);
}
return buf.toByteArray();
}