Android 앱을 개발 중입니다. 이제 html에 bbcode를 파싱하고 textview 내부에 표시합니다. textview는 사용자 정의 listview 안에 있습니다. AsyncTask에서 다운로드 한 이미지를 표시하려면 Html.ImageGetter()를 사용합니다.여러 asynctask를 관리하여 html 코드에서 여러 이미지를 다운로드하고 램을 유출 했습니까?
적은 수의 사진에 유용합니다. 그러나 앱에 40-50 장의 사진을 다운로드하도록 요청하면 40-50 개의 작업이 만들어지고 엉망이됩니다. 각 작업은 스트림을 열어 이미지를 다운로드합니다. 그런 다음 바이트를 비트 맵으로 디코딩하고 크기를 조정 한 다음 sdcard에 저장하고 비트 맵을 재활용합니다.
이제 앱에서이 모든 이미지를 동시에로드하는 경우 엄청난 양의 RAM을 사용합니다. 나는 48 메가 비트를 통과하도록 만들었다. .. 나는이 문제를 해결하는 방법에 대한 검색 :(16과 48 사이에 큰 틈이 나는 구글에서 AsyncTask를 코드 다운로드 :
을 그리고 3으로 풀 크기를 설정하지만이 도움이되지 않았다 . 나는 정말로 내가 숫양을 잃어 버리는 것을 알아낼 수 없다. 큰 작업 대기열을 열 자마자 숫양이 미쳐 간다. 약간의 이미지가 수신 된 후에 그것은 최악이된다. 나는 그것이 이미지이기 때문에 생각하지 않는다. 보기, 정보 및 서비스를 포함하여 응용 프로그램 자체가 13MB를 사용하며 나머지는 모두 여기에서 유출됩니다.
대기열 자체가 큰 RAM 할당을 수행합니까, 아니면 HTML .ImageGetter()가 엄청난 양을 누출했습니다. 어떻게 든 기억의? 이 작업을 수행하는 더 좋은 방법이 있습니까?
가 여기에 내가 이미지를로드 : 내가) Html.ImageGetter (전화 여기
public void LoadImages(String source) {
myurl = null;
try {
myurl = new URL(source);
} catch (MalformedURLException e) {
e.printStackTrace();
}
new DownloadImageFromPost().execute(myurl);
}
private class DownloadImageFromPost extends AsyncTask<URL, Integer, Bitmap> {
@Override
protected Bitmap doInBackground(URL... params) {
URL url;
Log.d(TAG, "Starting new image download");
try {
url = params[0];
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
int length = connection.getContentLength();
InputStream is = (InputStream) url.getContent();
byte[] imageData = new byte[length];
int buffersize = (int) Math.ceil(length/(double) 100);
int downloaded = 0;
int read;
while (downloaded < length) {
if (length < buffersize) {
read = is.read(imageData, downloaded, length);
} else if ((length - downloaded) <= buffersize) {
read = is.read(imageData, downloaded, length
- downloaded);
} else {
read = is.read(imageData, downloaded, buffersize);
}
downloaded += read;
publishProgress((downloaded * 100)/length);
}
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
length);
if (bitmap != null) {
Log.i(TAG, "Bitmap created");
} else {
Log.i(TAG, "Bitmap not created");
}
is.close();
return bitmap;
} catch (MalformedURLException e) {
Log.e(TAG, "Malformed exception: " + e.toString());
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.toString());
} catch (Exception e) {
}
return null;
}
protected void onPostExecute(Bitmap result) {
String name = Environment.getExternalStorageDirectory() + "/tempthumbs/" + myurl.toString().hashCode() +".jpg";
String rname = Environment.getExternalStorageDirectory() + "/tempthumbs/" + myurl.toString().hashCode() +"-t.jpg";
try {
if (result != null) {
hasExternalStoragePublicPicture(name);
ImageManager manager = new ImageManager(context);
Bitmap rezised = manager.resizeBitmap(result, 300, 300);
saveToSDCard(result, name, myurl.toString().hashCode() +".jpg");
saveToSDCard(rezised, rname, myurl.toString().hashCode() +"-t.jpg");
result.recycle();
rezised.recycle();
} else {
}
} catch(NullPointerException e) {
}
Log.d(TAG, "Sending images loaded announcement");
Intent i = new Intent(IMAGE_LOADED);
i.putExtra("image", name);
i.putExtra("source", myurl.toString());
i.putExtra("class", true);
context.sendBroadcast(i);
}
}
private boolean hasExternalStoragePublicPicture(String name) {
File file = new File(name);
if (file != null) {
file.delete();
}
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
return file.exists();
}
public void saveToSDCard(Bitmap bitmap, String name, String nam) {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
mExternalStorageAvailable = mExternalStorageWriteable = true;
Log.v(TAG, "SD Card is available for read and write "
+ mExternalStorageAvailable + mExternalStorageWriteable);
saveFile(bitmap, name, nam);
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
Log.v(TAG, "SD Card is available for read "
+ mExternalStorageAvailable);
} else {
mExternalStorageAvailable = mExternalStorageWriteable = false;
Log.v(TAG, "Please insert a SD Card to save your Video "
+ mExternalStorageAvailable + mExternalStorageWriteable);
}
}
private void saveFile(Bitmap bitmap, String fullname, String nam) {
ContentValues values = new ContentValues();
File outputFile = new File(fullname);
values.put(MediaStore.MediaColumns.DATA, outputFile.toString());
values.put(MediaStore.MediaColumns.TITLE, nam);
values.put(MediaStore.MediaColumns.DATE_ADDED, System
.currentTimeMillis());
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
Uri uri = context.getContentResolver().insert(
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);;
try {
OutputStream outStream = context.getContentResolver()
.openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.JPEG, 95, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
bitmap.recycle();
}
을 그리고,이 목록의 getView 안에 :
holder.content.setText(Html.fromHtml(
processor.preparePostText(posts.get(position).post_content),
new Html.ImageGetter() {
@Override public Drawable getDrawable(String source) {
Log.d("Forum Service", "image source: " + source);
if (imageSources.contains(source)) {
for (int x = 0; x < imageSources.size(); x++) {
if (source.equals(imageSources.get(x))) {
String tmp = oImages.get(x);
tmp = tmp.substring(0, tmp.length() - 4);
tmp = tmp + "-t.jpg";
Drawable d = Drawable.createFromPath(tmp);
try {
d.setBounds(0, 0, d.getIntrinsicWidth(),
d.getIntrinsicHeight());
} catch (NullPointerException e) {
}
Log.d("Forum Service", "Loaded image froms sdcard");
return d;
}
}
} else if (notLoadedImages.contains(source)) {
Log.d("Forum Service", "Waiting for image");
return null;
} else {
notLoadedImages.add(source);
LoadAllIcons loader = new LoadAllIcons(context);
loader.LoadImages(source);
Log.d("Forum Service", "Asked for image");
return null;
}
return null;
}
}, null));
감사합니다!
마지막으로 문제는 모든 작업이 동시에로드된다는 것입니다. 따라서 다운로드하는 동안 RAM에 40 개의 이미지가 할당됩니다.
private static final int CORE_POOL_SIZE = 2;
private static final int MAXIMUM_POOL_SIZE = 2;
private static final int KEEP_ALIVE = 1;
private static final BlockingQueue<Runnable> sWorkQueue =
new LinkedBlockingQueue<Runnable>(100);
FYI, 위 코드는 SD 카드에서로드하는 동안 UI 스레드를 여전히 잠급니다 (권장되지 않음). 또한 ListView를 표시하기 전에 모든 이미지가로드 될 때까지 기다리지 않으면 사용자가 화면에서 스크롤하여 행을 다시 만들 때까지 이미지가 준비된 후에도 ListView가 업데이트되지 않습니다. 내 관련 [질문] (http://stackoverflow.com/q/11712130/403455)를 참조하십시오. –