Reputation: 2461
I have created a simple Activity. The activity is responsible for downloading data from parse.com database and populating a linear layout. In the process, I am dynamically creating the linear layout with TextViews and ImageViews according according to the content.
The problem is that, whenever I try to download an image, I use as AsyncTask Downloading class, which results in slowing down the UI thread! I am currently trying to return the bitmap file from the AsyncTask Image downloading class using: returnedBitmap = new LoadImage().execute(src).get();
which might be responsible for slowing down the UI thread. I have to do this because the caller method geneterImageView
will return an imageview when it receives the bitmap file.
The complete Activity code:
public class MainActivity extends ActionBarActivity {
ArrayList<String> heightList = new ArrayList<String>();
ArrayList<String> reversedList = new ArrayList<String>();
ImageView imageView1;
Bitmap bitmap;
RelativeLayout parent_layout;
ParseObject user;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// imageView1 = (ImageView)findViewById(R.id.imageView1);
parent_layout = (RelativeLayout) findViewById(R.id.parent_layout);
login("[email protected]", "xyz");
}
private void loopThroughArrayAndAttach(){
LinearLayout llInner = new LinearLayout(this);
llInner.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
parent_layout.addView(llInner);
for (int i = 0; i < heightList.size(); i++) {
if (hasNoImagess(heightList.get(i)) == true) {
// No images.
TextView myText = geneterTextView(heightList.get(i));
llInner.addView(myText);
// geneterTextView(heightList.get(i));
} else {
ImageView myImage = geneterImageView(heightList.get(i));
llInner.addView(myImage);
// geneterImageView(heightList.get(i));
}
}
}
public static boolean hasNoImagess(String contents){
Document doc = Jsoup.parse(contents);
Element element = doc.body();
Elements elements = element.select("img");
if (elements.isEmpty()) {
return true;
} else {
return false;
}
}
public ImageView geneterImageView(String imgContent){
// Will need to run via background thread - like aysnc
// Extract the image file via jsoup
// Insert it into a imagevieww
// Inser that into a layout.
Log.d("IN IMAGE ", " " + imgContent);
Document doc = Jsoup.parse(imgContent);
Elements img = doc.getElementsByTag("img");
Bitmap returnedBitmap = null;
for (Element el : img) {
String src = el.absUrl("src");
System.out.println("src attribute is : " + src);
// new DownloadImageTask((ImageView)
// findViewById(R.id.imageView1)).execute(src);
try {
returnedBitmap = new LoadImage().execute(src).get();
// imageView1.setImageBitmap(returnedBitmap);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ImageView iv = new ImageView(this);
iv.setImageBitmap(returnedBitmap);
return iv;
}
public TextView geneterTextView(String textContent){
// Will need to run via background thread.
Log.i("In TEXT ", " " + textContent);
TextView tv = new TextView(this);
tv.setText(Html.fromHtml(textContent));
return tv;
}
// to download images
private class LoadImage extends AsyncTask<String, String, Bitmap> {
@Override
protected void onPreExecute(){
super.onPreExecute();
}
protected Bitmap doInBackground(String... args){
try {
bitmap = BitmapFactory.decodeStream((InputStream) new URL(args[0]).getContent());
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
protected void onPostExecute(Bitmap image){
if (image != null) {
} else {
Toast.makeText(MainActivity.this, "Image Does Not exist or Network Error", Toast.LENGTH_SHORT).show();
}
}
}
// to login to parse
private void login(final String username, String password){
ParseUser.logInInBackground(username, password, new LogInCallback() {
@Override
public void done(ParseUser user, ParseException e){
if (e == null) {
// if login sucess
// Start intent
// loginSuccess();
Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_SHORT).show();
CloudCallStudentPosts(user);
} else {
Toast.makeText(MainActivity.this, "Failure", Toast.LENGTH_SHORT).show();
}
}
});
}
// //to get data from parse
public void CloudCallStudentPosts(ParseObject s){
setRichStory(s);
}
private void setRichStory(ParseObject s){
// Simialr to setStory, once implemented delete setStory()
new AddStoryAsync(s).execute();
}
class AddStoryAsync extends AsyncTask<Void, Object, Void> {
private static final String TAG = "LazyListView";
ParseObject s;
public AddStoryAsync(ParseObject s) {
this.s = s;
Log.w("In richStory", "ParseObject Id: " + s.getObjectId());
}
@Override
protected void onPreExecute(){
}
@Override
protected Void doInBackground(Void... unused){
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("userid", this.s.getObjectId());
params.put("skip", 0);
ParseCloud.callFunctionInBackground("studentsPosts", params, new FunctionCallback<List<List<ParseObject>>>() {
@Override
public void done(List<List<ParseObject>> postList, com.parse.ParseException arg1){
if (postList == null) {
} else {
if (postList.size() > 0) {
// CustomWebView cwb;
for (int i = 0; i < postList.size(); i++) {
// final Post post = new Post();
if (postList.get(i).get(0).get("htmlContent") == null) {
}
if (postList.get(i).get(0).get("htmlContent") != null) {
Log.e("htmlContent parse", postList.get(i).get(0).get("htmlContent").toString());
// Parse HTML String using JSoup library
String HTMLSTring = postList.get(i).get(0).get("htmlContent").toString();
Document html = Jsoup.parse(HTMLSTring);
Elements paragraphs = html.getElementsByTag("p");
for (org.jsoup.nodes.Element paragraph : paragraphs) {
String paragraphText = paragraph.toString();
Log.e("paragraphText", paragraphText);
heightList.add(paragraphText);
}
loopThroughArrayAndAttach();
}
}
}
}
}
});
return (null);
}
@Override
protected void onProgressUpdate(Object... object){
Log.w("onProgressUpdate ", " " + object[0].getClass());
Log.w("adding to arrayPostList ", " " + object[0].getClass());
}
@Override
protected void onPostExecute(Void unused){
}
}
}
Is there any substitute for getting the bitmap from the AsyncTask and set it in the imageview? Should there be a logical alteration in the approach?
Upvotes: 1
Views: 969
Reputation: 778
try this : dont call get() @praveen. instead pass the imageview Reference in the constructor
WorkerThread mWorkerThread = new WorkerThread(mImageView);
mWorkerThread.execute(src);
private class WorkerThread extends AsyncTask<String, String, Bitmap> {
private WeakReference<ImageView> imageViewReference;
public WorkerThread(ImageView imageView) {
super();
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(String... args) {
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream((InputStream) new URL(args[0]).getContent());
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (result != null && imageViewReference.get() != null) {
imageViewReference.get().setImageBitmap(result);
}
}
}
Upvotes: 1
Reputation: 13616
As others have mentioned, your code has several design flaws which makes it difficult to provide you a solution to your problem.
The whole purpose of an AsyncTask
is to execute on a background thread. Executing networking and bitmap processing on the main thread will never work. You must refactor your code to accommodate this. Consider the following solution to this particular problem at least:
// to download images
private class LoadImage extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String... args) {
String imgContent = args[0];
Document doc = Jsoup.parse(imgContent);
Elements img = doc.getElementsByTag("img");
for (Element el : img) {
String src = el.absUrl("src");
System.out.println("src attribute is : " + src);
try {
return BitmapFactory.decodeStream((InputStream) new URL(src).getContent());
} catch (Exception e) {
// log
}
}
return null;
}
protected void onPostExecute(Bitmap b) {
ImageView iv = new ImageView(MainActivity.this);
iv.setImageBitmap(b);
llInner.addView(iv);
}
}
You can then do something like:
for (int i = 0; i < heightList.size(); i++) {
new LoadImage(heightList.get(i)).execute();
}
However, this may not be desirable depending on how many AsyncTask
s you end up creating. But this is the idea.
Upvotes: 0
Reputation: 6941
Don't call get()
method on AsyncTask
it makes main thread to wait for AsyncTask
to complete. If you really want to start something only after AsyncTask
completes put that into onPostExecute()
of your AsynTask
Upvotes: 0