The problem is , when I set the async download task at custom adapter getView function, it return
ImageLoader cannot be resolved to a type
error. The class is in different package of same project, it normally can import but in this case it only show error. How to fix the problem? Thanks for helping
LeadersAdapter.java
public class LeadersAdapter extends ArrayAdapter<Record> {
public LeadersAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
public LeadersAdapter(Context context, int resource, List<Record> items) {
super(context, resource, items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.leader_record_row, null);
}
Record p = getItem(position);
if (p != null) {
ImageView pic = (ImageView) v.findViewById(R.id.profile_pic);
TextView name = (TextView) v.findViewById(R.id.name);
TextView pts = (TextView) v.findViewById(R.id.pts);
new ImageLoader().execute(pic,p.url);
name.setText(p.name);
pts.setText(p.pts);
}
return v;
}
}
ImageLoader.java
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;
class ImageLoader extends AsyncTask<Object, Void, Bitmap> {
private static String TAG = "ImageLoader";
public InputStream input;
public ImageView view;
public String imageURL;
public ImageLoader(String text){
}
#Override
protected Bitmap doInBackground(Object... params) {
try {
view = (ImageView) params[0];
imageURL = (String) params[1];
URL url = new URL(imageURL);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
input.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#Override
protected void onPostExecute(Bitmap result) {
if (result != null && view != null) {
view.setImageBitmap(result);
}
}
}
Your ImageLoader class (which is not defined as public) is using the default access modifier, package-private, so it is only visible in it's own package.
Changing...
class ImageLoader [...]
to...
public class ImageLoader [...]
should fix your accessibility problem.
Also, I would highly recommend looking into an existing image loading library (like Universal Image Loader) instead of baking your own.
I'd recommend Square's Picasso lib, which is easy to use.
Simple one line to load image from web into ImageView.
Ex:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
Related
I'm trying to access my application without internet and I want the application to inform that there is no connection instead of closing alone giving an error.
When my internet is disabled, I cannot access the application. It simply closes by itself returning the error:
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp.test, PID: 20245
java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Arrays$ArrayList.<init>(Arrays.java:3741)
at java.util.Arrays.asList(Arrays.java:3728)
at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:164)
at com.myapp.test.utils.adapters.CustomGridView.<init>(CustomGridView.java:35)
at com.myapp.test.fragment.FragmentHome.onCreateView(FragmentHome.java:193)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2346)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1428)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3248)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3200)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:195)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:597)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1392)
at android.app.Activity.performStart(Activity.java:7260)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3009)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1840)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6872)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
E/MQSEventManagerDelegate: failed to get MQSService.
As I understand it, I need to return a null value, but I can't implement it in my code. Can someone help me?
Here is the code for my GridView:
package com.myapp.test.utils.adapters;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.myapp.test.R;
import com.myapp.test.utils.image.RoundedSquareImageView;
import com.myapp.test.utils.text.DinTextView;
import java.io.InputStream;
/**
* Created by jaiso on 13-02-2018.
*/
public class CustomGridView extends ArrayAdapter<String>{
private String[] profilename;
private String[] imagepath;
private String[] ImgUserStatus;
private Activity context;
Bitmap bitmap;
public CustomGridView(Activity context, String[] profilename, String[] imagepath, String[] ImgUserStatus) {
super(context, R.layout.item_home_grid_users,profilename);
this.context=context;
this.profilename=profilename;
this.imagepath=imagepath;
this.ImgUserStatus=ImgUserStatus;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent){
View r=convertView;
ViewHolder viewHolder=null;
if(r==null){
LayoutInflater layoutInflater=context.getLayoutInflater();
r=layoutInflater.inflate(R.layout.item_home_grid_users,null,true);
viewHolder=new ViewHolder(r);
r.setTag(viewHolder);
}
else {
viewHolder=(ViewHolder)r.getTag();
}
viewHolder.tvw1.setText(profilename[position]);
new GetImageFromURL(viewHolder.ivw).execute(imagepath[position]);
new GetImageFromURLStatus(viewHolder.ImgStatusOnlineOffline).execute(ImgUserStatus[position]);
return r;
}
class ViewHolder{
DinTextView tvw1;
RoundedSquareImageView ivw;
ImageView ImgStatusOnlineOffline;
LinearLayout LinearFavIconHidden;
ViewHolder(View v){
tvw1=(DinTextView)v.findViewById(R.id.fragm_feed_txt_name);
ivw=(RoundedSquareImageView)v.findViewById(R.id.fragm_feed_profile_image);
ImgStatusOnlineOffline=(ImageView)v.findViewById(R.id.fragm_home_user_img_status_online_offline);
}
}
public class GetImageFromURL extends AsyncTask<String,Void,Bitmap>
{
RoundedSquareImageView imgView;
public GetImageFromURL(RoundedSquareImageView imgv)
{
this.imgView=imgv;
}
#Override
protected Bitmap doInBackground(String... url) {
String urldisplay=url[0];
bitmap=null;
try{
InputStream ist=new java.net.URL(urldisplay).openStream();
bitmap= BitmapFactory.decodeStream(ist);
}
catch (Exception ex)
{
ex.printStackTrace();
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap){
super.onPostExecute(bitmap);
imgView.setImageBitmap(bitmap);
}
}
public class GetImageFromURLStatus extends AsyncTask<String,Void,Bitmap>
{
ImageView imgViewStatus;
public GetImageFromURLStatus(ImageView imgvStatus)
{
this.imgViewStatus=imgvStatus;
}
#Override
protected Bitmap doInBackground(String... url) {
String urldisplay=url[0];
bitmap=null;
try{
InputStream ist=new java.net.URL(urldisplay).openStream();
bitmap= BitmapFactory.decodeStream(ist);
}
catch (Exception ex)
{
ex.printStackTrace();
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap){
super.onPostExecute(bitmap);
imgViewStatus.setImageBitmap(bitmap);
}
}
}
Now, your app works whenever the device is connected to the internet, but it crashes when the internet is not available.
So, you want to check if you're connected to the internet, and if not, then you want to prevent any code that tries to parse any URL.
In order to check whether your device is connected to the internet or not use the below method which return true if your device is connected to the internet.
public boolean isOnline(Context context) {
boolean isConnected = false;
ConnectivityManager mConnectivityMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
// Checking internet connectivity
NetworkInfo activeNetwork = null;
if (mConnectivityMgr != null) {
activeNetwork = mConnectivityMgr.getActiveNetworkInfo(); // Deprecated in API 29
}
isConnected = activeNetwork != null;
} else {
Network[] allNetworks = mConnectivityMgr.getAllNetworks(); // added in API 21 (Lollipop)
for (Network network : allNetworks) {
NetworkCapabilities networkCapabilities = mConnectivityMgr.getNetworkCapabilities(network);
if (networkCapabilities != null) {
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
|| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET))
isConnected = true;
}
}
}
return isConnected;
}
Add isOnline() method in your custom adapter class which is called CustomGridView.
In your code you tries to access the internet in your adapter, specifically within getView() method using the your custom AsyncTask class. So change this method to check if your are online or not.
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View r = convertView;
ViewHolder viewHolder = null;
if (r == null) {
LayoutInflater layoutInflater = context.getLayoutInflater();
r = layoutInflater.inflate(R.layout.item_home_grid_users, null, true);
viewHolder = new ViewHolder(r);
r.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) r.getTag();
}
viewHolder.tvw1.setText(profilename[position]);
if (isOnline(parent.getContext())) {
new GetImageFromURL(viewHolder.ivw).execute(imagepath[position]);
new GetImageFromURLStatus(viewHolder.ImgStatusOnlineOffline).execute(ImgUserStatus[position]);
}
return r;
}
check this answer if you want to do more about internet functionality.
I am trying to display images in a listview with AsyncTask but I am getting an error. Saying...
Attempt to invoke virtual method 'java.lang.String
java.lang.Object.toString()' on a null object reference
This is error is happening on
public LoadImage(ImageView imv) {
this.imv = imv;
this.path = imv.getTag().toString();
}
And
LoadImage loadImage = new LoadImage(imageView);
Bitmap bitmap = loadImage.doInBackground();
Here is LoadImage.java
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Environment;
import android.view.View;
import android.widget.ImageView;
import java.io.File;
/**
* Created by Yudii on 27/05/2016.
*/
class LoadImage extends AsyncTask<Object, Void, Bitmap>{
private ImageView imv;
private String path;
public LoadImage(ImageView imv) {
this.imv = imv;
this.path = imv.getTag().toString();
}
#Override
protected Bitmap doInBackground(Object... params) {
Bitmap bitmap = null;
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + path);
if (file.exists()) {
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
if (!imv.getTag().toString().equals(path)) {
/* The path is not same. This means that this
image view is handled by some other async task.
We don't do anything and return. */
// return;
}
if(result != null && imv != null){
imv.setVisibility(View.VISIBLE);
imv.setImageBitmap(result);
}else{
imv.setVisibility(View.GONE);
}
}
}
And here is CustomList.java
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final Integer[] imageId;
public CustomList(Activity context,
String[] web, Integer[] imageId) {
super(context, R.layout.list_single, web);
this.context = context;
this.imageId = imageId;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.list_single, null, true);
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
LoadImage loadImage = new LoadImage(imageView);
Bitmap bitmap = loadImage.doInBackground();
imageView.setImageResource(imageId[position]);
return rowView;
}
}
And here is MainActivity.java
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
ListView list;
String[] web = {
"Google Plus",
"Twitter",
"Tall",
};
Integer[] imageId = {
R.drawable.gggggggggg,
R.drawable.hhhhhhhhhh,
R.drawable.ttttttttttt
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomList adapter = new
CustomList(MainActivity.this, web, imageId);
list=(ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(MainActivity.this, "You Clicked at " +web[+ position], Toast.LENGTH_SHORT).show();
}
});
}
}
You need to change loadImage.execute(); instead of Bitmap bitmap = loadImage.doInBackground();
Why do you need AsyncTask? Try to use library Picasso and open images by one string:
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + path);
Picasso.with(context).load(file).into(imageView);
Bitmap objects are very weight and you need to clean memory after each Bitmap image for prevent OutOfMemoryError. I recommend you to use libraries.
Add this in your dependencies :-
compile 'com.squareup.picasso:picasso:2.5.2'
and then load your image :-
Picasso.with(this)
.load(drawerImage) // ImagePath
.placeholder( R.mipmap.download)
.error( R.mipmap.add_photo)
.into(imageDrawerView); //ImageView
1,Reason:
As I see, in your getView function:
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
// You need to set tag to your image view
// Ex: imageView.setTag("your_image_file_path") below this line
your imageView has no tag so the below code will get NullPointerException.
public LoadImage(ImageView imv) {
this.imv = imv;
this.path = imv.getTag().toString(); // Crashed here.
}
Also, I see in your getView function has this code:
imageView.setImageResource(imageId[position]);
That means "your ImageView will set resource corresponding to defined imageId array". So you no need AsyncTask class, let remove it and change your getView like below:
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.list_single, parent, false);
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
// Remove below code
// LoadImage loadImage = new LoadImage(imageView);
// Bitmap bitmap = loadImage.doInBackground();
imageView.setImageResource(imageId[position]);
return rowView;
}
Your Asynctask class is needed whenever you use path of image file, not drawable resources.
2, Improvement:
You can learn more about ViewHolder pattern when using ListView, RecyclerView to improve performance, from Google Search. Below is an example with your current code:
#Override
public View getView(int position, View view, ViewGroup parent) {
View holder = null;
if (view == null) {
holder = new ViewHolder();
LayoutInflater inflater = context.getLayoutInflater();
view = inflater.inflate(R.layout.list_single, parent, false);
holder.imageView = (ImageView) view.findViewById(R.id.img);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.imageView.setImageResource(imageId[position]);
return view;
}
static class ViewHolder { // should be static class
ImageView imageView;
}
I have a RecyclerView with a GridLinearLayout and a custom adapter. The content of each item is a picture downloaded using a json and parsing it.
Basically is a grid of pictures.
Everything works almost fine, but however, when scrolling down the content, and the going up again, it shows the previous views in each item for less than a second, and then show the proper picture again.
What could I do to prevent or fix this? Thanks in advance for any help and/or guidance you could provide.
This is the adapter code:
package jahirfiquitiva.project.adapters;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import jahirfiquitiva.project.activities.WallpapersActivity;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.Ion;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import jahirfiquitiva.project.R;
public class WallpapersAdapter extends RecyclerView.Adapter<WallpapersAdapter.WallsHolder> {
public interface ClickListener {
void onClick(WallsHolder view, int index, boolean longClick);
}
private ArrayList<HashMap<String, String>> data;
private final Context context;
private boolean usePalette = true;
private final ClickListener mCallback;
private final Map<String, Palette> mPaletteCache = new WeakHashMap<>();
public WallpapersAdapter(Context context, ClickListener callback) {
this.context = context;
this.data = new ArrayList<>();
this.mCallback = callback;
}
public void setData(ArrayList<HashMap<String, String>> data) {
this.data = data;
notifyDataSetChanged();
}
#Override
public WallsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
return new WallsHolder(inflater.inflate(R.layout.wallpaper_item, parent, false));
}
#Override
public void onBindViewHolder(final WallsHolder holder, int position) {
Animation anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);
HashMap<String, String> jsondata = data.get(position);
holder.name.setText(jsondata.get(WallpapersActivity.NAME));
final String wallurl = jsondata.get(WallpapersActivity.WALL);
holder.wall.startAnimation(anim);
holder.wall.setTag(wallurl);
Ion.with(context)
.load(wallurl)
.asBitmap()
.setCallback(new FutureCallback<Bitmap>() {
#Override
public void onCompleted(Exception e, Bitmap result) {
holder.progressBar.setVisibility(View.GONE);
if (e != null) {
e.printStackTrace();
} else if (holder.wall.getTag() != null && holder.wall.getTag().equals(wallurl)) {
holder.wall.setImageBitmap(result);
if (usePalette) {
Palette p;
if (mPaletteCache.containsKey(wallurl)) {
p = mPaletteCache.get(wallurl);
} else {
p = new Palette.Builder(result).generate();
mPaletteCache.put(wallurl, p);
}
if (p != null) {
Palette.Swatch wallSwatch = p.getVibrantSwatch();
if (wallSwatch != null) {
holder.titleBg.setBackgroundColor(wallSwatch.getRgb());
holder.titleBg.setAlpha(1);
holder.name.setTextColor(wallSwatch.getTitleTextColor());
holder.name.setAlpha(1);
}
}
}
}
}
});
}
#Override
public int getItemCount() {
return data.size();
}
public class WallsHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public final View view;
public final ImageView wall;
public final TextView name;
public final ProgressBar progressBar;
public final LinearLayout titleBg;
WallsHolder(View v) {
super(v);
view = v;
wall = (ImageView) v.findViewById(R.id.wall);
name = (TextView) v.findViewById(R.id.name);
progressBar = (ProgressBar) v.findViewById(R.id.progress);
titleBg = (LinearLayout) v.findViewById(R.id.titlebg);
view.setOnClickListener(this);
view.setOnLongClickListener(this);
}
#Override
public void onClick(View v) {
int index = getLayoutPosition();
if (mCallback != null)
mCallback.onClick(this, index, false);
}
#Override
public boolean onLongClick(View v) {
int index = getLayoutPosition();
if (mCallback != null)
mCallback.onClick(this, index, true);
return false;
}
}
}
Overwrite onViewRecycled (VH holder) to set the image to null.
Like this:
public void onViewRecycled (VH holder) {
holder.wall.setImageBitmap(null);
}
As the name suggests RecyclerView recycles the views to optimize memory so it displays the content of previous view. Since you are loading the image from internet it takes little time to load the image so the content of previous image could be observed. You can do one of the following things.
1) Set a default image from local resource before loading actual image, preferably a small size image to preserve memory.something like this
//load default image first
holder.wall.setImageResource(R.id.your_default_image_resource);
//load actual image
Ion.with(context)
.load(wallurl)
.asBitmap()
.setCallback(new FutureCallback<Bitmap>() {
#Override
public void onCompleted(Exception e, Bitmap result) {
holder.progressBar.setVisibility(View.GONE);
if (e != null) {
e.printStackTrace();
} else if (holder.wall.getTag() != null && holder.wall.getTag().equals(wallurl)) {
holder.wall.setImageBitmap(result);
if (usePalette) {
Palette p;
if (mPaletteCache.containsKey(wallurl)) {
p = mPaletteCache.get(wallurl);
} else {
p = new Palette.Builder(result).generate();
mPaletteCache.put(wallurl, p);
}
if (p != null) {
Palette.Swatch wallSwatch = p.getVibrantSwatch();
if (wallSwatch != null) {
holder.titleBg.setBackgroundColor(wallSwatch.getRgb());
holder.titleBg.setAlpha(1);
holder.name.setTextColor(wallSwatch.getTitleTextColor());
holder.name.setAlpha(1);
}
}
}
}
}
});
2) Set the ImageView visibility to GONE/INVISIBLE before loading the image and make it VISIBLE again after the image is loaded.
//hide the imageview
holder.wall.setVisibility(View.INVISIBLE);
Ion.with(context)
.load(wallurl)
.asBitmap()
.setCallback(new FutureCallback<Bitmap>() {
#Override
public void onCompleted(Exception e, Bitmap result) {
holder.progressBar.setVisibility(View.GONE);
if (e != null) {
e.printStackTrace();
} else if (holder.wall.getTag() != null && holder.wall.getTag().equals(wallurl)) {
//show the imageview and set bitmap
holder.wall.setVisibility(View.VISIBLE);
holder.wall.setImageBitmap(result);
if (usePalette) {
Palette p;
if (mPaletteCache.containsKey(wallurl)) {
p = mPaletteCache.get(wallurl);
} else {
p = new Palette.Builder(result).generate();
mPaletteCache.put(wallurl, p);
}
if (p != null) {
Palette.Swatch wallSwatch = p.getVibrantSwatch();
if (wallSwatch != null) {
holder.titleBg.setBackgroundColor(wallSwatch.getRgb());
holder.titleBg.setAlpha(1);
holder.name.setTextColor(wallSwatch.getTitleTextColor());
holder.name.setAlpha(1);
}
}
}
}
}
});
I think you should add place holder like this:
Ion.with(context).load("http://example.com/image.png")
.withBitmap()
.placeholder(R.drawable.placeholder_image)
.error(R.drawable.error_image)
.intoImageView(imageView);
or set default image at first.
holder.wall.setImageResource(R.drawable.placeholder_image);
I am trying to get images from url and set it in a listview through my listviewadapter class. I am getting NULLPOINTEREXCEPTION at openConnection()
in getBitmapFromUrl method at the end.
Here is my code:
ListViewAdapter.java
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ListViewAdapter extends BaseAdapter {
public String msgType[] = new String[8];
public String msgData[] = new String[8];
public String msgTimeStamp[] = new String[8];
Bitmap[] myBitmap = new Bitmap[8];
public Activity context;
int positionX;
URL urlX;
public LayoutInflater inflater;
public ListViewAdapter(Activity context, String[] type, String[] data,
String[] timestamp) {
super();
this.context = context;
this.msgType = type;
this.msgData = data;
this.msgTimeStamp = timestamp;
this.inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return msgData.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public static class ViewHolder {
ImageView imgView;
TextView txtType;
TextView txtData;
TextView txtTimestamp;
Bitmap myBitmap;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.list_item, null);
holder.imgView = (ImageView) convertView.findViewById(R.id.image);
holder.txtType = (TextView) convertView.findViewById(R.id.type);
holder.txtData = (TextView) convertView.findViewById(R.id.data);
holder.txtTimestamp = (TextView) convertView
.findViewById(R.id.timestamp);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
// holder.imgView.setImageBitmap(myBitmap[position]);
holder.txtType.setText(msgType[position]);
holder.txtTimestamp.setText(msgTimeStamp[position]);
if (msgType[position].equals("0"))
holder.txtData.setText(msgData[position]);
else {
holder.txtData.setText("");
URL url = null;
try {
url = new URL(msgData[position]);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
urlX=url;
positionX=position;
try {
Thread t = new Thread(new Runnable() {
public void run(){
myBitmap[positionX] = getBitmapFromUrl(urlX);
}
});
t.start();
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
holder.imgView.setImageBitmap(myBitmap[position]);
}
return convertView;
}
public Bitmap getBitmapFromUrl(URL url1) {
Bitmap Bitmap = null;
try {
HttpURLConnection connection = (HttpURLConnection) url1
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap = BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
}
return Bitmap;
}
}
EDIT:
Thread t = new Thread(new Runnable() {
public void run(){
myBitmap[positionX] = getBitmapFromUrl(urlX);
}
});
t.start();
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
LOGCAT(after edit):
04-03 12:01:26.860: E/AndroidRuntime(11944): FATAL EXCEPTION: Thread-1155
04-03 12:01:26.860: E/AndroidRuntime(11944): java.lang.NullPointerException
04-03 12:01:26.860: E/AndroidRuntime(11944): at com.appquest.flatcassign.ListViewAdapter.getBitmapFromUrl(ListViewAdapter.java:127)
04-03 12:01:26.860: E/AndroidRuntime(11944): at com.appquest.flatcassign.ListViewAdapter$1.run(ListViewAdapter.java:107)
04-03 12:01:26.860: E/AndroidRuntime(11944): at java.lang.Thread.run(Thread.java:856)
Hi I update your base adpter class see blow with implement of the picasso library, you just have to copy and replace the code, sure help you. do not forget to add the jar file.
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ListViewAdapter extends BaseAdapter {
public String msgType[] = new String[8];
public String msgData[] = new String[8];
public String msgTimeStamp[] = new String[8];
public Activity context;
public LayoutInflater inflater;
public ListViewAdapter(Activity context, String[] type, String[] data,
String[] timestamp) {
super();
this.context = context;
this.msgType = type;
this.msgData = data;
this.msgTimeStamp = timestamp;
this.inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return msgData.length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
public static class ViewHolder {
ImageView imgView;
TextView txtType;
TextView txtData;
TextView txtTimestamp;
Bitmap myBitmap;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.list_item, null);
holder.imgView = (ImageView) convertView.findViewById(R.id.image);
holder.txtType = (TextView) convertView.findViewById(R.id.type);
holder.txtData = (TextView) convertView.findViewById(R.id.data);
holder.txtTimestamp = (TextView) convertView
.findViewById(R.id.timestamp);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
// holder.imgView.setImageBitmap(myBitmap[position]);
holder.txtType.setText(msgType[position]);
holder.txtTimestamp.setText(msgTimeStamp[position]);
if (msgType[position].equals("0"))
holder.txtData.setText(msgData[position]);
else {
holder.txtData.setText("");
Picasso.with(context).load(msgData[position]).into(holder.imgView);
}
return convertView;
}
}
Thank you.
I am trying to get images from URLs in a string array and my app is crashing. It is crashing on line 110: InputStream input = connection.getInputStream(); What am I doing wrong?
Here is my class:
package kyfb.android.kyfb.com.kyfb;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.Image;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Created by KFB on 8/12/14.
*/
class ActionAlertsAdapter extends BaseAdapter {
private LayoutInflater inflater;
public ActionAlertsAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
public int getCount() {
// TODO Auto-generated method stub
return ActionAlertsFragment.title.length;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
if(convertView == null){
convertView = inflater.inflate(R.layout.item_feed, null);
holder = new ViewHolder();
holder.lytItemFeed = (RelativeLayout) convertView.findViewById(R.id.lytItemFeed);
holder.txtTitle= (TextView) convertView.findViewById(R.id.txtTitle);
holder.txtPubDate = (TextView) convertView.findViewById(R.id.txtPubDate);
holder.thumbnail = (ImageView) convertView.findViewById(R.id.thumbnail);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
if((position%2)!=0){
holder.lytItemFeed.setBackgroundColor(Color.TRANSPARENT);
}else{
holder.lytItemFeed.setBackgroundColor(Color.TRANSPARENT);
}
holder.txtTitle.setText(ActionAlertsFragment.title[position]);
holder.txtPubDate.setText(ActionAlertsFragment.pubDate[position]);
Bitmap bitmap = getBitmapFromURL(ActionAlertsFragment.thumb[position]);
if(bitmap == null) {
holder.thumbnail.setImageResource(R.drawable.kyfb);
}
else {
holder.thumbnail.setImageBitmap(bitmap);
}
holder.txtTitle.setTextColor(Color.WHITE);
holder.txtPubDate.setTextColor(Color.WHITE);
return convertView;
}
public Bitmap getBitmapFromURL(String imageUrl) {
try {
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
static class ViewHolder {
TextView txtTitle, txtPubDate;
ImageView thumbnail;
RelativeLayout lytItemFeed;
}
}
This doesn't directly answer your question, but you might want to consider using an image loading library such as Picasso or Volley. There is a lot of complexity--some subtle, some not so much--in loading images from network, even more so when you're trying to do it in a ListView. Both of those libraries (and several others out there) take care of all or most of the complexity for you.
You should move your method in an AsyncTask. You are downloading stuff on your main thread.