parse images with jsoup - java

AI have some problems again))
I have a code which parse links from file. Into the file i have some links to forum treads. Like this:
http://vao-priut.org/image/cherepashka-metis-gollandskoi-ovcharki-s-72
http://vao-priut.org/image/taiga-s-26
and etc.
I try to parse images with this code:
class ParseMyPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
try {
input = new URL("https://gist.githubusercontent.com/akhorevich/5b849373dc9abaf921b3/raw/18e79ab6a0c0be007a2a4590e4e176184ced311a/links");
sc = new Scanner(input.openStream());
while(sc.hasNextLine()){
String link = sc.nextLine();
doc = Jsoup.connect(link).get();
Elements names = doc.select("div.node-title");
// Elements images = doc.select("div.node div.content img");
Elements imgs = doc.select("div.node div.content img");
for (Element img : imgs) {
Element myImage = img;
String imgSrc = myImage.attr("src");
InputStream inp = new java.net.URL(imgSrc).openStream();
// Decode Bitmap
bitmap = BitmapFactory.decodeStream(inp);
}
for(Element name: names) {
mData.add(name.text());
}
if(mData.size() == 0) {
mData.add("Empty result");
}
}
} catch (IOException e) {
e.printStackTrace();
mData.clear();
mData.add("Exception: " + e.toString());
}
return text; // получаем весь текст
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
sectorC_adapter = new SectorC_Adapter(getActivity());
mListView.setAdapter(sectorC_adapter);
}
}
But it parse image only from last link and add it to all items. How can i make some images bufferedArray or something like this? Thank you!!!
P.S. I forget about my BaseAdapter:
class SectorC_Adapter extends BaseAdapter{
private Context c;
SectorC_Adapter(Context c){
this.c = c;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Object getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView==null){
inflater = (LayoutInflater)c
.getSystemService(c.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.sector_row, parent,false);
}else {
row = convertView;
}
tvInfo = (TextView)row.findViewById(R.id.dog_name);
tvInfo.setText(mData.get(position).toString());
dog_view = (ImageView)row.findViewById(R.id.dog_view);
dog_view.setImageBitmap(bitmap);
return row;
}
}

In here you are not adding your image to any list
for (Element img : imgs) {
Element myImage = img;
String imgSrc = myImage.attr("src");
InputStream inp = new java.net.URL(imgSrc).openStream();
// Decode Bitmap
bitmap = BitmapFactory.decodeStream(inp);
///HERE YOU SHOULD ADD YOUR BITMAP TO ALL ELEMENTS
///eg. allImages.add(bitmap); or whatever.
}
I suppose that bitmap is some sort of field that is added to your all elements so basicly only the last state will be stored. What you have to do is to add your bitmap inside for-loop.

Related

Define text color based on value using AsyncTask

So basically my AsyncTask get the value from the url and when i execute i wanna show green text or red text if contains ("-").
I have search around and none of the option worked for me. i do have a RecyclerView.ViewHolder but don't know how to incorporate before i execute. Everything works, except the colors.
Thank you in advance
Activity
public class BTCData extends AsyncTask<Void,RecyclerView.ViewHolder,Void> {
String data = "";
String dataParsed1h ="";
String dataParsed24h ="";
String dataParsed7d ="";
String percent_change_1h = "";
String percent_change_24h = "";
String percent_change_7d = "";
Activity activity;
List<Model> items;
public BTCData() {
}
#Override
protected Void doInBackground(Void... voids) {
try {
URL url = new URL ("https://...");
HttpURLConnection httpURLConnection = (java.net.HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while (line != null){
line = bufferedReader.readLine();
data = data+line;
}
JSONArray JA = new JSONArray(data);
for(int i=0 ;i< JA.length(); i++){
JSONObject JO = (JSONObject) JA.get(i);
percent_change_1h = "1H " + JO.getString("percent_change_1h") + "%";
percent_change_24h = "24H " + JO.getString("percent_change_24h") + "%";
percent_change_7d = "7D " + JO.getString("percent_change_7d") + "%" ;
dataParsed1h = dataParsed1h + percent_change_1h;
dataParsed24h = dataParsed24h + percent_change_7d;
dataParsed7d = dataParsed7d + percent_change_24h;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
MainActivity.btc_percent_change_1h.setText(this.dataParsed1h);
MainActivity.btc_percent_change_24h.setText(this.dataParsed24h);
MainActivity.btc_percent_change_7d.setText(this.dataParsed7d);
}
}```
**View Holder**
public class CoinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Adapter adapter;
boolean isLoading;
Activity activity;
List<Model> items;
int visibleThreshold = 5,lastVisibleItem, totalItemcount;
public void setAdapter(Adapter adapter) {
this.adapter = adapter;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(activity)
.inflate(R.layout.activity_main,parent,false);
return new CoinViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Model item = items.get(position);
CoinViewHolder holderItem = (CoinViewHolder)holder;
holderItem.btc_percent_change_1h.setTextColor(item.getPercentage_change_1h().contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32"));
holderItem.btc_percent_change_24h.setTextColor(item.getPercentage_change_24h().contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32"));
holderItem.btc_percent_change_7d.setTextColor(item.getPercentage_change_7d().contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32"));
}
#Override
public int getItemCount() {
return items.size();
}
public void setLoader() {isLoading = true;}
public void updateData (List<Model> models)
{
this.items = models;
notifyDataSetChanged();
}
**on Activity**
public static TextView btc_percent_change_1h;
public static TextView btc_percent_change_24h;
public static TextView btc_percent_change_7d;
//Percentage
btc_percent_change_1h = (TextView) findViewById(R.id.btc_percent_change_1h);
btc_percent_change_24h = (TextView) findViewById(R.id.btc_percent_change_24h);
btc_percent_change_7d = (TextView) findViewById(R.id.btc_percent_change_7d);
and finally call...
BTCData process = new BTCData();
process.execute();
This is because for setting color you are doing in onBindViewHolder when in that case data would be 0 only without red sign and later you are setting data but after that onBindViewHolder is not called and hence changes are not reflecting.
The way you are doing all this is not ideal way and would suggest you to read design patterns to implement it in proper way.
Maybe is not the best option, but it works
#Override
protected void onPostExecute(CoinAdapter aVoid) {
super.onPostExecute(aVoid);
MainActivity.btc_percent_change_1h.setTextColor((this.dataParsed1h.contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32")));
MainActivity.btc_percent_change_1h.setText(this.dataParsed1h);
MainActivity.btc_percent_change_24h.setTextColor((this.dataParsed24h.contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32")));
MainActivity.btc_percent_change_24h.setText(this.dataParsed24h);
MainActivity.btc_percent_change_7d.setTextColor((this.dataParsed7d.contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32")));
MainActivity.btc_percent_change_7d.setText(this.dataParsed7d);
}
You can achieve it like. Get value in adapter according to position and change it color like this. Then cocatinate both string and show it. You can test it on multiple devices it will run and show exact in every devices.
String status = getColoredSpanned(act.getResources().getString(R.string.order_status),"#3EA7BD");
String variable_status =getColoredSpanned(act.getResources().getString(R.string.status_order_pending),"#E23941");
String text = status+variable_status;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
myViewHolder.tv_order_product_status.setText(Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY), TextView.BufferType.SPANNABLE);
} else {
myViewHolder.tv_order_product_status.setText(Html.fromHtml(text), TextView.BufferType.SPANNABLE);
}

ViewPager Not getting Images from server

I am using ViewPager in my app and fetch the data(Images) from server(with JSON). Even if runs smoothly no image is shown in the viewpager.
I read so many tutorial regarding this, but nobody solve my problem. Please tell me where i am wrong...
Here is my code:
view_pager.xml
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="40dp" />
image_view.xml
<ImageView
android:id="#+id/image_adapter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"/>
ViewPager_Adapter.java
public class ViewPager_Adapter extends PagerAdapter {
private String urls;
private LayoutInflater inflater;
private Context context;
ArrayList<String> mylist;
public ViewPager_Adapter(Context context, ArrayList<String> mylist) {
this.context = context;
this.urls = urls;
this.mylist = mylist;
inflater = LayoutInflater.from(context);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public int getCount() {
return mylist.size();
}
#Override
public Object instantiateItem(ViewGroup view, int position) {
View imageLayout = inflater.inflate(R.layout.image_view, null);
assert imageLayout != null;
final ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image_adapter);
Glide.with(context)
.load(mylist.get(position))
.into(imageView);
view.addView(imageLayout,0);
return imageLayout;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
#Override
public Parcelable saveState() {
return null;
}
}
View_Pager.Java
public class View_Pager extends Fragment {
private static ViewPager mPager;
JSONArray responsearray = null;
String imageOne;
private static final String TAG_PHOTO_ONE = "Gallery_Full";
ArrayList<String> myList;
HashMap<String, String> get;
ViewPager_Adapter viewpager_adapter;
LinearLayout addimages;
int REQUEST_CODE = 100;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.view_pager, null);
mPager = view.findViewById(R.id.viewpager);
new GetImages().execute(true);
return view;
}
class GetImages extends AsyncTask<Boolean, Void, String> {
#Override
protected String doInBackground(Boolean... booleans) {
ImageApi imageApi = new ImageApi();
String result = null;
try {
result = imageApi.galleryget(sharedPreferences.getString("id", ""));
JSONObject object = new JSONObject(result);
if (object.getString("error").equalsIgnoreCase("false")) {
responsearray = object.getJSONArray("response");
return "true";
} else {
String errormsg = object.getString(result);
return errormsg;
}
} catch (ApiException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (s != null) {
if (s.equalsIgnoreCase("true")) {
showList(responsearray);
}
}
}
}
public void showList(final JSONArray responsearray) {
try {
for (int i = 0; i < responsearray.length(); i++) {
JSONObject responseObject = responsearray.getJSONObject(i);
Log.e("COUNT" + i, String.valueOf(responseObject));
imageOne = responseObject.getString(TAG_PHOTO_ONE);
get = new HashMap<>();
get.put(TAG_PHOTO_ONE, imageOne);
myList = new ArrayList<>();
myList.add(String.valueOf(get));
}
viewpager_adapter = new ViewPager_Adapter(getActivity(), myList);
String test = String.valueOf(myList);
String imgpath = getString(R.string.imgpath);
String finalimgpath = imgpath + imageOne;
Log.e("FINALPATH", finalimgpath);
} catch (JSONException e) {
e.printStackTrace();
}
mPager.setAdapter(viewpager_adapter);
viewpager_adapter.notifyDataSetChanged();
}
}
Use this code for showList() as you are not populating you're arrayList properly the data is being over write in one position .
So , what you have to do is initialize it out side of for loop .
public void showList(final JSONArray responsearray) {
try {
//here
myList = new ArrayList<>();
for (int i = 0; i < responsearray.length(); i++) {
JSONObject responseObject = responsearray.getJSONObject(i);
Log.e("COUNT" + i, String.valueOf(responseObject));
imageOne = responseObject.getString(TAG_PHOTO_ONE);
get = new HashMap<>();
get.put(TAG_PHOTO_ONE, imageOne);
myList.add(String.valueOf(get));
}
viewpager_adapter = new ViewPager_Adapter(getActivity(), myList);
String test = String.valueOf(myList);
String imgpath = getString(R.string.imgpath);
String finalimgpath = imgpath + imageOne;
Log.e("FINALPATH", finalimgpath);
} catch (JSONException e) {
e.printStackTrace();
}
mPager.setAdapter(viewpager_adapter);
viewpager_adapter.notifyDataSetChanged();
}
Edit
Also if your final image path is as below then you have to update your code in adapter for image path as follow.
Update position in view.addView() too.
String test = String.valueOf(mylist.get(position));
String imgpath = getString(R.string.imgpath);
String finalimgpath = imgpath + test;
Glide.with(context)
.load(finalimgpath)
.into(imageView);
view.addView(imageLayout,position);
return imageLayout;
In your For loop you are initialising your list everytime
for (int i = 0; i < responsearray.length(); i++) {
JSONObject responseObject = responsearray.getJSONObject(i);
Log.e("COUNT" + i, String.valueOf(responseObject));
imageOne = responseObject.getString(TAG_PHOTO_ONE);
get = new HashMap<>();
get.put(TAG_PHOTO_ONE, imageOne);
myList = new ArrayList<>(); // THIS IS WRONG. don't initialise every time
myList.add(String.valueOf(get)); // THIS IS ALSO WRONG. you are adding hashmap object to list
}
So make your for loop like this
myList = new ArrayList<>();
for (int i = 0; i < responsearray.length(); i++) {
JSONObject responseObject = responsearray.getJSONObject(i);
Log.e("COUNT" + i, String.valueOf(responseObject));
imageOne = responseObject.getString(TAG_PHOTO_ONE);
get = new HashMap<>();
get.put(TAG_PHOTO_ONE, imageOne);
myList.add(imageOne);
}

loading images to a recyclerview using a thread

So I have a Recyclerview which holding items with images, I want to load images into the items but when I do that I got a lot of fps drops.
I read that I need to use another thread for the network part and I tried to do that as you can see, and it seems good to me but I can't figure out how to stop the fps drops and make the scrolling in the Recyclerview smooth, this Recyclerview supposed to hold between 10 and 100. Am I supposed to run the activity in a thread?
Note: The fps drops occur with 10 items.
calling to the HttpWrapper.LoadImageFromWebOperations function in OnBindViewHolder.
HomeAdapter.java
public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.HomeViewHolder>{
private Context context;
private ArrayList<RecipeModel> items;
public HomeAdapter(Context context, ArrayList<RecipeModel> items) {
this.context = context;
this.items = items;
}
#Override
public HomeAdapter.HomeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.home_item,null);
HomeAdapter.HomeViewHolder holder = new HomeAdapter.HomeViewHolder(v);
return holder;
}
public void addItem(RecipeModel item){
this.items.add(item);
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(HomeAdapter.HomeViewHolder holder, final int position) {
RecipeModel model = items.get(position);
holder.name.setText(model.getName());
holder.directions.setText(model.getDirections()[0]);
Drawable drawable = HttpWrapper.LoadImageFromWebOperations(model.getImageSource());
holder.image.setImageDrawable(drawable);
}
#Override
public int getItemCount() {
return items.size();
}
class HomeViewHolder extends RecyclerView.ViewHolder{
TextView name;
TextView directions;
ImageView image;
public HomeViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.recipe_name);
directions = (TextView) itemView.findViewById(R.id.recipe_directions);
image = (ImageView) itemView.findViewById(R.id.recipe_image);
}
}
HttpWrapper.java
public class HttpWrapper {
String responseMsg = "";
private OkHttpClient client;
private Request request;
public static final String base_url = "http://kingtimmy.pythonanywhere.com";
public static final String home_route = "/home/";
public HttpWrapper() {
client = new OkHttpClient();
}
public ArrayList<RecipeModel> get_home_recipes(int recipe_num){
ArrayList<RecipeModel> models = new ArrayList<RecipeModel>();
request = new Request.Builder().url(base_url + home_route + String.valueOf(recipe_num)).build();
responseMsg = "";
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
responseMsg = "Error: " + e.getMessage();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
responseMsg = response.body().string();
}
});
while(responseMsg.equals("")){
continue;
}
String[] jsons = responseMsg.split("]-]");
for (int i = 0; i < jsons.length; i++){
models.add(makeRecipeModel(jsons[i]));
}
return models;
}
public RecipeModel makeRecipeModel(String msg){
JSONObject nodeRoot = null;
RecipeModel model;
try {
nodeRoot = new JSONObject(msg);
String[] directions = nodeRoot.get("directions").toString().split("\\n");
String[] ingredients = nodeRoot.get("ingredients").toString().split("\\n");
String image_source = nodeRoot.get("image").toString();
String source_url = nodeRoot.get("source_url").toString();
String name = nodeRoot.get("name").toString();
int id = Integer.valueOf(nodeRoot.get("id").toString());
model = new RecipeModel(directions,ingredients,image_source,source_url,name,id);
} catch (JSONException e) {
model = null;
}
return model;
}
public static Drawable LoadImageFromWebOperations(final String url) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Drawable> callable = new Callable<Drawable>() {
#Override
public Drawable call() {
try {
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
} catch (Exception e) {
System.out.println("Exc=" + e);
return null;
}
}
};
Future<Drawable> future = executor.submit(callable);
// future.get() returns 2 or raises an exception if the thread dies, so safer
try {
Drawable d = future.get();
executor.shutdown();
return d;
} catch (Exception e) {
return null;
}
}
What am I doing wrong?
Instead of writing your own thread and code to fetch, parse, decode and load the image, give Glide a try. It does all that for you with a simple single line code and loads the image in your ImageView

How can a user import images into the app?

I'm editing an open source app: A simple coloring page app for kids. I need to be able to make the user import his own images to be colored. Here is the full source code.
And here is the code for loading images from R.drawable:
public class StartNewActivity extends NoTitleActivity implements View.OnClickListener
{
// This is an expensive operation.
public static int randomOutlineId()
{
return new ResourceLoader().randomOutlineId();
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Apparently this cannot be set from the style.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
setContentView(R.layout.start_new);
GridView gridview = (GridView) findViewById(R.id.start_new_grid);
gridview.setAdapter(new ImageAdapter(this));
}
public void onClick(View view)
{
setResult(view.getId());
finish();
}
private static class ResourceLoader
{
ResourceLoader()
{
// Use reflection to list resource ids of thumbnails and outline
// images.First, we list all the drawables starting with the proper
// prefixes into 2 maps.
Map<String, Integer> outlineMap = new TreeMap<String, Integer>();
Map<String, Integer> thumbMap = new TreeMap<String, Integer>();
Field[] drawables = R.drawable.class.getDeclaredFields();
for (int i = 0; i < drawables.length; i++)
{
String name = drawables[i].getName();
try
{
if (name.startsWith(PREFIX_OUTLINE))
{
outlineMap.put(name.substring(PREFIX_OUTLINE.length()),
drawables[i].getInt(null));
}
if (name.startsWith(PREFIX_THUMB))
{
thumbMap.put(name.substring(PREFIX_THUMB.length()),
drawables[i].getInt(null));
}
}
catch (IllegalAccessException e)
{
}
}
Set<String> keys = outlineMap.keySet();
keys.retainAll(thumbMap.keySet());
_outlineIds = new Integer[keys.size()];
_thumbIds = new Integer[keys.size()];
int j = 0;
Iterator<String> i = keys.iterator();
while (i.hasNext())
{
String key = i.next();
_outlineIds[j] = outlineMap.get(key);
_thumbIds[j] = thumbMap.get(key);
j++;
}
}
public Integer[] getThumbIds()
{
return _thumbIds;
}
public Integer[] getOutlineIds()
{
return _outlineIds;
}
public int randomOutlineId()
{
return _outlineIds[new Random().nextInt(_outlineIds.length)];
}
private static final String PREFIX_OUTLINE = "outline";
private static final String PREFIX_THUMB = "thumb";
private Integer[] _thumbIds;
private Integer[] _outlineIds;
}
private class ImageAdapter extends BaseAdapter
{
ImageAdapter(Context c)
{
_context = c;
_resourceLoader = new ResourceLoader();
}
public int getCount()
{
return _resourceLoader.getThumbIds().length;
}
public Object getItem(int i)
{
return null;
}
public long getItemId(int i)
{
return 0;
}
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(_context);
imageView.setLayoutParams(new GridView.LayoutParams(145, 145));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
imageView.setOnClickListener(StartNewActivity.this);
}
else
{
imageView = (ImageView) convertView;
}
imageView.setImageResource(_resourceLoader.getThumbIds()[position]);
imageView.setId(_resourceLoader.getOutlineIds()[position]);
return imageView;
}
private Context _context;
private ResourceLoader _resourceLoader;
}
}
You can use File to write the imported file of the user. Use something like this.
public boolean write(byte[] data, File file)
{
if (file.getParentFile().exists()) {
if (file.exists()) {
file.delete();
}
} else {
file.getParentFile().mkdirs();
}
try{
OutputStream output = new FileOutputStream(file);
output.write(data);
output.close();
return true;
}catch(Exception e){
Log.v("FileManager", "Error writing file.", e);
return false;
}
}
Sample:
String pathName = "/mnt/sdcard/Android/data/com.company.project/files/tmp/photo.png";
Bitmap bmp = BitmapFactory.decodeFile(pathName);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
write(byteArray, new File("/mnt/sdcard/Android/data/com.company.project/files/photo.png");

How can I download images from the network in a ListView without lag?

I have a ListAdapter that contains a bunch of images that are being downloaded from the internet. When I scroll up and down there seems to be a performance hit and things get jerky. How can I resolve this?
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.message_row, null);
}
STMessage aMessage = messages.get(position);
if (aMessage != null) {
TextView usernameTextView = (TextView) v.findViewById(R.id.usernameTextView);
TextView bodyTextView = (TextView) v.findViewById(R.id.bodyTextView);
TextView dateTextView = (TextView) v.findViewById(R.id.dateTextView);
ImageView avatarImageView = (ImageView)v.findViewById(R.id.avatarImageView);
if (usernameTextView != null) {
usernameTextView.setText(Html.fromHtml(aMessage.getUser_login()));
}
if (bodyTextView != null) {
bodyTextView.setText(aMessage.getBody());
//linkify urls
Linkify.addLinks(bodyTextView, Linkify.WEB_URLS);
//linkify symbols
Pattern symbolMatcher = Pattern.compile("/(?:^|\\s|[\\.(\\+\\-\\,])(?:\\$?)\\$((?:[0-9]+(?=[a-z])|(?![0-9\\.\\:\\_\\-]))(?:[a-z0-9]|[\\_\\.\\-\\:](?![\\.\\_\\.\\-\\:]))*[a-z0-9]+)/i");
String symbolURL = "content://com.stocktwits.activity/symbol/";
Linkify.addLinks(bodyTextView, symbolMatcher, symbolURL);
}
if (dateTextView != null) {
dateTextView.setText(aMessage.getUpdated_at());
}
if (avatarImageView != null) {
imageDownloader.download(aMessage.getAvatar_url(), avatarImageView);
}
}
return v;
}
Use Lazy Loading of Images - Lazy load of images in ListView
Maybe by using a Threads pool (queue) and placing a temporal image in the meantime?
Here is a nice way to go about it.
At least I think its nice. I did it :)
here is the class I used to load the ImageView in the background.
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
private ImageView destination;
private String cachedFile;
private Date startTime;
private DownloadCompletedListener completedListener;
public DownloadImageTask(ImageView destination, String cachedFile, DownloadCompletedListener completedListener)
{
this.destination = destination;
this.cachedFile = cachedFile;
this.startTime = new Date();
this.completedListener = completedListener;
}
protected Bitmap doInBackground(String... urls)
{
Bitmap result = getBitmapFromURL(urls[0]);
if (result != null)
{
try {
FileOutputStream out = new FileOutputStream(HSAppUtil.getFilePath(getFilenameFromUrl(urls[0])));
result.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
}
else
{
result = Bitmap.createBitmap(1,1,Config.ARGB_8888);
}
return result;
}
public String getHost() {
return "http://MyMainHost";
}
public Bitmap getBitmapFromURL(String fileUrl) {
String newFileUrl = null;
if (!fileUrl.contains("://"))
{
newFileUrl = getHost() + fileUrl;
}
else
{
newFileUrl = fileUrl;
}
URL myFileUrl = null;
try {
myFileUrl = new URL(newFileUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
length++;
return BitmapFactory.decodeStream(is);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Bitmap result)
{
synchronized (destination)
{
Date lastUpdated = (Date)destination.getTag();
if (lastUpdated == null || lastUpdated.before(startTime))
{
boolean handled = false;
if (completedListener != null)
{
handled = completedListener.handleDownloadCompleted(destination, result);
}
if (!handled && destination != null)
{
destination.setTag(startTime);
destination.setImageBitmap(result);
}
}
result = null;
}
}
public interface DownloadCompletedListener {
boolean handleDownloadCompleted(ImageView i, Bitmap b);
}
}
then when you want to use it, You would call it like this.
new DownloadImageTask(imView, fileUrl, completedListener).execute(fileUrl);
and send the imView to the UI. it will load the image in when it downloads it.
Please give me your honest feedback.

Categories