I am following this tutorial for implementing ViewPager in my project. I have done that using static images successfully. Now I want to change it so that images are retrieved from urls and displayed in ViewPager. Below is my code.
Where should I add the method for downloading images and how to set it
to my ViewPager?
Any help will be greatly appreciated.
MainActivity:
public class MainActivity extends AppCompatActivity {
private ArrayList<Integer> images;
private BitmapFactory.Options options;
private ViewPager viewPager;
private View btnNext, btnPrev;
private FragmentStatePagerAdapter adapter;
private LinearLayout thumbnailsContainer;
private final static int[] resourceIDs = new int[]{R.mipmap.a, R.mipmap.b,
R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f, R.mipmap.g};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
images = new ArrayList<>();
//find view by id
viewPager = (ViewPager) findViewById(R.id.view_pager);
thumbnailsContainer = (LinearLayout) findViewById(R.id.container);
btnNext = findViewById(R.id.next);
btnPrev = findViewById(R.id.prev);
btnPrev.setOnClickListener(onClickListener(0));
btnNext.setOnClickListener(onClickListener(1));
setImagesData();
// init viewpager adapter and attach
adapter = new ViewPagerAdapter(getSupportFragmentManager(), images);
viewPager.setAdapter(adapter);
inflateThumbnails();
}
private View.OnClickListener onClickListener(final int i) {
return new View.OnClickListener() {
#Override
public void onClick(View v) {
if (i > 0) {
//next page
if (viewPager.getCurrentItem() < viewPager.getAdapter().getCount() - 1) {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
}
} else {
//previous page
if (viewPager.getCurrentItem() > 0) {
viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
}
}
}
};
}
private void setImagesData() {
for (int i = 0; i < resourceIDs.length; i++) {
images.add(resourceIDs[i]);
}
}
private void inflateThumbnails() {
for (int i = 0; i < images.size(); i++) {
View imageLayout = getLayoutInflater().inflate(R.layout.item_image, null);
ImageView imageView = (ImageView) imageLayout.findViewById(R.id.img_thumb);
imageView.setOnClickListener(onChagePageClickListener(i));
options = new BitmapFactory.Options();
options.inSampleSize = 3;
options.inDither = false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), images.get(i), options );
imageView.setImageBitmap(bitmap);
//set to image view
imageView.setImageBitmap(bitmap);
//add imageview
thumbnailsContainer.addView(imageLayout);
}
}
private View.OnClickListener onChagePageClickListener(final int i) {
return new View.OnClickListener() {
#Override
public void onClick(View v) {
viewPager.setCurrentItem(i);
}
};
}
}
PageFragment class:
public class PageFragment extends Fragment {
private int imageResource;
private Bitmap bitmap;
public static PageFragment getInstance(int resourceID) {
PageFragment f = new PageFragment();
Bundle args = new Bundle();
args.putInt("image_source", resourceID);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
imageResource = getArguments().getInt("image_source");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_page, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
BitmapFactory.Options o = new BitmapFactory.Options();
o.inSampleSize = 4;
o.inDither = false;
bitmap = BitmapFactory.decodeResource(getResources(), imageResource, o);
imageView.setImageBitmap(bitmap);
}
#Override
public void onDestroy() {
super.onDestroy();
bitmap.recycle();
bitmap = null;
}
}
ViewPager Adapter class:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private List<Integer> images;
public ViewPagerAdapter(FragmentManager fm, List<Integer> imagesList) {
super(fm);
this.images = imagesList;
}
#Override
public Fragment getItem(int position) {
return PageFragment.getInstance(images.get(position));
}
#Override
public int getCount() {
return images.size();
}
}
To use ViewPager for images you have to make a adapter which extends PagerAdapter like as below:
public class ImagePagerAdapter extends PagerAdapter {
Context context;
LayoutInflater layoutInflater;
ArrayList<String> arrayList;
public ImagePagerAdapter(Context context, ArrayList<String> arrayList) {
this.context = context;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.arrayList = arrayList;
}
#Override
public int getCount() {
if(arrayList != null){
return arrayList.size();
}
return 0;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((LinearLayout) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View itemView = layoutInflater.inflate(R.layout.image_viewpager_layout, container, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.viewPagerItem_image1);
Picasso.with(context).load(arrayList.get(position))
.placeholder(R.drawable.image_uploading)
.error(R.drawable.image_not_found).into(imageView);
container.addView(itemView);
return itemView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((LinearLayout) object);
}
}
And xml layout for adapter is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/viewPagerItem_image1"
android:layout_width="match_parent"
android:layout_height="250dp"
android:scaleType="fitXY"
android:src="#drawable/ic_launcher"/>
</LinearLayout>
For Download Images from URL you have to use AsyncTask.
For that follow below Example of DownloadImageFromAsyncTask.
new LoadImage().execute("http://www.sumtrix.com/images/sumtrix/Android-Wallpaper-HD.jpg");
Set your url to above url.
private class LoadImage extends AsyncTask<String, String, Bitmap> {
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Loading Image...");
dialog.show();
}
#Override
protected Bitmap doInBackground(String... params) {
try {
bitmap = BitmapFactory.decodeStream((InputStream) new URL(params[0]).getContent());
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
if (result != null) {
img.setImageBitmap(result);
dialog.dismiss();
} else {
dialog.dismiss();
Toast.makeText(getApplicationContext(), "Image Does Not Exist...",
Toast.LENGTH_LONG).show();
}
}
}
for that you have to add permission in AndroidManifest.xml file
<uses-permission android:name="android.permission.INTERNET" />
IMO you should set your image here, your imageResource is your imgUrl and using a lib such as: UniversalImageLoader, Volley, Picasso... we have many libs to support loading image with url.
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
BitmapFactory.Options o = new BitmapFactory.Options();
o.inSampleSize = 4;
o.inDither = false;
bitmap = BitmapFactory.decodeResource(getResources(), imageResource, o);
imageView.setImageBitmap(bitmap);
}
you should call the picdownloadertask in onViewCreated()
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
new PicDownladerTask().execute(url)
}
class PicDownloaderTask extends AsyncTask {
#Override
protected Bitmap doInBackground(String... strings) {
Bitmap bitmap = getBitmap(strings[0]);
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
BitmapFactory.Options o = new BitmapFactory.Options();
o.inSampleSize = 4;
o.inDither = false;
bitmap = BitmapFactory.decodeResource(getResources(), imageResource, o);
imageView.setImageBitmap(bitmap);
}
this is the method to get images from url
public static Bitmap getBitmap(String url)
{
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(70000);
conn.setReadTimeout(70000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
// OutputStream os = new FileOutputStream(f);
// Utils.CopyStream(is, os);
// os.close();
bitmap = BitmapFactory.decodeStream(is);
conn.disconnect();
// bitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex){
ex.printStackTrace();
if(ex instanceof OutOfMemoryError){}
// memoryCache.clear();
return null;
}
}
I use Picasso library when I need to show image from a URL. It is extremely simple to use.
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
Picasso.with(this)
.load(image_url)
.into(imageView);
}
You can see references and download library from this, Picasso
Hope it's helpful.
Use this code to download and show on imageView.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout_here);
new DownloadImageTask((ImageView) findViewById(R.id.imageView1))
.execute("http://java.sogeti.nl/JavaBlog/wp-content/uploads/2009/04/android_icon_256.png");
}
public void onClick(View v) {
startActivity(new Intent(this, IndexActivity.class));
finish();
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
}
add internet permission in AndroidManifest.xml.
<uses-permission android:name="android.permission.INTERNET" />
see this link for more detail
create a async task and download the image in do in background
#Override
protected Bitmap doInBackground(String... url) {
this.url = url[0];
final DefaultHttpClient client = new DefaultHttpClient();
final org.apache.http.client.methods.HttpGet getRequest = new org.apache.http.client.methods.HttpGet(
url[0]);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
LoggerUtils.logWarn("ImageDownloader", "Error "
+ statusCode + " while retrieving bitmap from "
+ url[0]);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
final Bitmap bitmap = BitmapFactory
.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
getRequest.abort();
}
Related
I have a ListView with a custom adapter. Every row has an ImageView that I render using a Bitmap, but my current code blocks the UI thread as I am using get() after executing my AsyncTask that downloads the bitmaps. I would like to change my code and access the imageViews in the onPostExecute() or something similar. So that the rows already display without waiting for all sprites to load.
Adapter class (download is triggered here)
public class PokemonAdapter extends ArrayAdapter<PokemonPOJO> implements View.OnClickListener{
private ArrayList<PokemonPOJO> dataSet;
Context mContext;
private int lastPosition = -1;
// View lookup cache
private static class ViewHolder {
TextView txtName;
TextView txtCP;
TextView txtGenderShiny;
ImageView sprite;
Button btnDelete;
}
public PokemonAdapter(ArrayList<PokemonPOJO> data, Context context) {
super(context, R.layout.row_pokemon, data);
this.dataSet = data;
this.mContext=context;
}
#Override
public void onClick(View v) {
int position=(Integer) v.getTag();
Object object= getItem(position);
PokemonPOJO dataModel=(PokemonPOJO)object;
switch (v.getId())
{
case R.id.btn_delete:
FirebaseDatabase.getInstance().getReference("pokemons").child(dataModel.getUid()).removeValue();
Toast.makeText(getContext(), "Pokemon removed!", Toast.LENGTH_SHORT).show();
this.remove(dataModel);
break;
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
PokemonPOJO dataModel = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.row_pokemon, parent, false);
viewHolder.txtName = (TextView) convertView.findViewById(R.id.text_name);
viewHolder.txtCP = (TextView) convertView.findViewById(R.id.text_cp);
viewHolder.txtGenderShiny = (TextView) convertView.findViewById(R.id.text_gendershiny);
viewHolder.sprite = (ImageView) convertView.findViewById(R.id.img_sprite);
viewHolder.btnDelete = (Button)convertView.findViewById(R.id.btn_delete);
result=convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
lastPosition = position;
viewHolder.txtName.setText(dataModel.getName());
viewHolder.txtCP.setText("CP: " + Integer.toString(dataModel.getCP()));
viewHolder.txtGenderShiny.setText(dataModel.getGender() + (dataModel.isShiny() ? " (Shiny)" : ""));
viewHolder.btnDelete.setOnClickListener(this);
try {
Bitmap bm = new DownloadImageTask().execute(dataModel.getSpriteUrl()).get();
viewHolder.sprite.setImageBitmap(bm);
} catch (Exception e) {
e.printStackTrace();
}
viewHolder.btnDelete.setTag(position);
// Return the completed view to render on screen
return convertView;
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
#Override
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap bm = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
bm = BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return bm;
}
}
Fragment with ListView
public class MyPokemonFragment extends Fragment {
private FirebaseAuth auth;
private DatabaseReference pokemonDb;
private TextView text_noPokemon;
private ListView listViewPokemon;
private static PokemonAdapter adapter;
private populateListViewTask populateListView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_mypokemon,null);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
auth = FirebaseAuth.getInstance();
listViewPokemon = view.findViewById(R.id.list_pokemon);
text_noPokemon= view.findViewById(R.id.text_noPokemon);
Query getUserPokemon = FirebaseDatabase.getInstance().getReference("pokemons").orderByChild("userUid").equalTo(auth.getCurrentUser().getUid());
getUserPokemon.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if(!snapshot.hasChildren()) {
text_noPokemon.setText("You have not added any Pokémon yet.");
}
else {
TreeMap<String, Pokemon> pokemons = new TreeMap<>();
for (DataSnapshot pokemon : snapshot.getChildren()) {
pokemons.put(pokemon.getKey(), pokemon.getValue(Pokemon.class));
}
populateListView = new populateListViewTask();
populateListView.execute(pokemons);
}
}
#Override
public void onCancelled(DatabaseError databaseError) { }
});
}
#Override
public void onDestroy() {
super.onDestroy();
if(populateListView != null && populateListView.getStatus() == AsyncTask.Status.RUNNING)
populateListView.cancel(true);
}
private class populateListViewTask extends AsyncTask<TreeMap<String, Pokemon>, Void, ArrayList<PokemonPOJO>> {
#Override
protected ArrayList<PokemonPOJO> doInBackground(TreeMap<String, Pokemon>... maps) {
ArrayList<PokemonPOJO> pojos = new ArrayList<>();
HttpURLConnection connection = null;
BufferedReader reader = null;
Iterator it = maps[0].entrySet().iterator();
while(it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
Pokemon p = (Pokemon)pair.getValue();
try {
URL url = new URL("https://pokeapi.co/api/v2/pokemon/" + p.getPokedexNr() + "/");
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
JSONObject j = new JSONObject(buffer.toString());
String name = j.getString("name");
String spriteUrl = (p.isShiny() ? j.getJSONObject("sprites").getString("front_shiny") : j.getJSONObject("sprites").getString("front_default"));
PokemonPOJO pojo = new PokemonPOJO((String)pair.getKey(), p.getPokedexNr(), name, spriteUrl, p.isShiny(), p.getGender(), p.getCP());
pojos.add(pojo);
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.disconnect();
try {
if (reader != null)
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return pojos;
}
#Override
protected void onPostExecute (ArrayList < PokemonPOJO > pojos) {
adapter = new PokemonAdapter(pojos, getContext());
listViewPokemon.setAdapter(adapter);
}
}
}
Pokemon row XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/img_sprite"
android:layout_width="96dp"
android:layout_height="96dp"
android:scaleType="fitCenter" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="left|center_vertical"
android:orientation="vertical">
<TextView
android:id="#+id/text_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/black"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/text_cp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp" />
<TextView
android:id="#+id/text_gendershiny"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="end"
android:orientation="vertical">
<Button
android:id="#+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:backgroundTint="#color/colorPrimary"
android:text="DELETE"
android:textColor="#ffffff"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
You are having performance issues because you are calling the get() method on your AsyncTask. The get() method basically causes the main thread to wait until the code in the AsyncTask completes execution before the main thread continues executing other instructions. Why Google added this method is curious to say the least. So do this to fix your code.
Create a new Java class file. Name the file "DownloadImageTask" and add this code:
public interface DownloadImageListener {
void onCompletedImageDownload(Bitmap bm);
}
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
private static final String TAG = DownloadImageTask.class.getSimpleName();
private DownloadImageListener mListener;
private String imageUrl = "";
public DownloadImageTask(String imageUrl, DownloadImageListener listener){
this.imageUrl = imageUrl;
this.mListener = listener;
}
#Override
protected Bitmap doInBackground(String... urls) {
Bitmap bm = null;
try {
InputStream in = new java.net.URL(imageUrl).openStream();
bm = BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return bm;
}
protected void onPostExecute(Bitmap bm) {
mListener.onCompletedImageDownload(bm);
}
}
If you have any issues adding the public interface to the "DownloadImageTask" Java file just create a separate Java file name "DownloadImageListener" and put the interface code in there.
Set your code to query the AsyncTask.
Change the Adapter code inside your getView() from this:
try {
Bitmap bm = new DownloadImageTask().execute(dataModel.getSpriteUrl()).get();
viewHolder.sprite.setImageBitmap(bm);
} catch (Exception e) {
e.printStackTrace();
}
to this:
try {
DownloadImageListener listener = new DownloadImageListener() {
#Override
public void onCompletedImageDownload(Bitmap bm) {
if(bm != null){
viewHolder.sprite.setImageBitmap(bm);
}
}
};
String imageUrl = dataModel.getSpriteUrl();
DownloadImageTask downloadImageTask = new DownloadImageTask(imageUrl, listener);
downloadImageTask.execute();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
This allows your AsyncTask to execute and when the Bitmap is returned the listener is triggered in the onPostExecute() method sending the Bitmap to your ListView in the onCompletedImageDownload() callback method.
Additional Info:
To improve performance even further you could create a caching model to save and retrieve images from the device if you have already downloaded them in the past. But that requires some really advanced techniques--and gets really tricky when images you wish to download might change from time to time.
I have a gallery of images that shows the images in a recyclerviewusing glide and by clicking on each image in the recyclerview that image open in a view pager. every thing is ok in the beginning the recyclerview is fine, the images open in a viewpager and sliding in viewpager are all fine. but when i press back to close the viewpager and goback to recyclerview suddenly the allocated memory raises to about 400 MB!!!
there are 8 images that are about 490*420 pixel and 72 KB size.
MainGallery.xml
<android.support.v7.widget.RecyclerView
android:id="#+id/recView_Gallery1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
>
</android.support.v7.widget.RecyclerView>
<Button
android:id="#+id/btn_retry_Gallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="تلاش مجدد"
android:textSize="16sp"
android:visibility="gone"
android:layout_gravity="center"
android:gravity="center"/>
</android.support.design.widget.CoordinatorLayout>
GalleryEnter.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorAccent">
<ImageView
android:id="#+id/iv_photoGallety"
android:adjustViewBounds="true"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:layout_margin="2dp"
android:layout_width="match_parent"
android:background="#android:color/white"/>
</LinearLayout>
ImageDetail.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorAccent"
tools:context="com.parsroyan.restaurant.imageDetailActivity">
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.design.widget.CoordinatorLayout>
MainGalleryActivity.java
public class GalleryMain_Activity extends AppCompatActivity {
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
public static RecyclerView recListMenuTypes;
public static ImageAdapter mta;
ArrayList<ImageGallery> data = new ArrayList<>();
Button btn_retry;
TextView tv_message;
ImageView imv_message;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gallery_main_);
btn_retry = (Button) findViewById(R.id.btn_retry_Gallery);
recListMenuTypes = (RecyclerView) findViewById(R.id.recView_Gallery1)
;
recListMenuTypes.setHasFixedSize(true);
GridLayoutManager mLayoutManager = new
GridLayoutManager(GalleryMain_Activity.this, 2);
recListMenuTypes.setLayoutManager(mLayoutManager);
//LinearLayoutManager llm = new
LinearLayoutManager(GalleryMain_Activity.this);
//llm.setOrientation(LinearLayoutManager.VERTICAL);
//recListMenuTypes.setLayoutManager(llm);
recListMenuTypes.setItemAnimator(new DefaultItemAnimator());
mta = new ImageAdapter(GalleryMain_Activity.this, data);
recListMenuTypes.setAdapter(mta);
Check_Connection_Retrive();
btn_retry.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Check_Connection_Retrive();
}
});
}
private void alertView1(String message,boolean success) {
final TypedArray styledAttributes =
GalleryMain_Activity.this.getTheme().obtainStyledAttributes(new int[] {
android.R.attr.actionBarSize });
int Y = (int) styledAttributes.getDimension(0, 0);
styledAttributes.recycle();
LayoutInflater inflater = getLayoutInflater();
View toastLayout = inflater.inflate(R.layout.custom_toast,
(ViewGroup)
findViewById(R.id.custom_toast_layout));
tv_message = (TextView)
toastLayout.findViewById(R.id.custom_toast_message);
tv_message.setText(message);
Toast toast = new Toast(getApplicationContext());
toast.setDuration(Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP | Gravity.START |
Gravity.FILL_HORIZONTAL,0,Y);
toast.setView(toastLayout);
imv_message = (ImageView)
toastLayout.findViewById(R.id.custom_toast_image);
if(!success){
toastLayout.setBackgroundColor(Color.parseColor("#cc0000"));
imv_message.setBackgroundResource(android.R.drawable.ic_dialog_alert);
}
else {
imv_message.setBackgroundResource(android.R.drawable.ic_dialog_info);
}
toastLayout.setAlpha(.8f);
toast.show();
}
public void Check_Connection_Retrive()
{
if(InternetConnection.checkConnection(getApplicationContext(),this))
{
btn_retry.setVisibility(View.GONE);
new FetchGallery().execute();
}
else
{
btn_retry.setVisibility(View.VISIBLE);
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
private class FetchGallery extends AsyncTask<String, String, String> {
TransparentProgressDialog pdLoading = new
TransparentProgressDialog
(GalleryMain_Activity.this,R.drawable.progress_circle);
HttpURLConnection conn;
URL url = null;
#Override
protected void onPreExecute() {`enter code here`
super.onPreExecute();
//pdLoading.setMessage("\tLoading...");
pdLoading.setCancelable(false);
//pdLoading.setProgress(10);
pdLoading.show();
}
#Override
protected String doInBackground(String... params) {
try {
url = new URL("My_URL");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "1";
}
try {
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("GET");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return "2";
}
try {
int response_code = conn.getResponseCode();
// Check if successful connection made
if (response_code == HttpURLConnection.HTTP_OK) {
// Read data sent from server
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
// Pass data to onPostExecute method
return (result.toString());
} else {
return "3";
}
} catch (IOException e) {
return "4";
} finally {
conn.disconnect();
}
}
#Override
protected void onPostExecute(String result) {
//this method will be running on UI thread
pdLoading.dismiss();
switch(result) {
case "1":
break;
case "2":
break;
case "3":
break;
case "4":
break;
default:
try {
btn_retry.setVisibility(View.GONE);
JSONArray jArray = new JSONArray(result);
for (int i = 0; i < jArray.length(); i++) {
//JSONObject json_data = jArray.getJSONObject(i);
ImageGallery image = new ImageGallery();
//image.name = json_data.getString("name");
image.title = jArray.get(i).toString();
image.url = "MY_URL" + image.title;
data.add(image);
}
// Setup and Handover data to recyclerview
mta.notifyDataSetChanged();
recListMenuTypes.addOnItemTouchListener(new
RecyclerViewTouchListener(getApplicationContext(), recListMenuTypes, new
RecyclerViewClickListener() {
#Override
public void onClick(View view, int position) {
Intent intent = new Intent(GalleryMain_Activity.this,
imageDetailActivity.class);
intent.putParcelableArrayListExtra("data", data);
intent.putExtra("pos", position);
startActivity(intent);
}
#Override
public void onLongClick(View view, int position){
}
}));
} catch (JSONException e) {
Toast.makeText(GalleryMain_Activity.this,
e.toString(), Toast.LENGTH_LONG).show();
}
}
}
}
}
ImageAdapter.java
public class ImageAdapter extends
RecyclerView.Adapter<ImageAdapter.MenuViewHolder> {
private List<ImageGallery> imageGalleryList;
private Context context;
protected int lastPosition = -1;
public ImageAdapter(Context Context,List<ImageGallery> contactList)
{
this.imageGalleryList = contactList;
this.context = Context;
}
#Override
public int getItemCount() {
return imageGalleryList.size();
}
#Override
public void onBindViewHolder(ImageAdapter.MenuViewHolder menuViewHolder,
int i) {
final ImageGallery m = imageGalleryList.get(i);
Glide.with(context).load("MyURL"+m.title)
.thumbnail(.1f)
.crossFade()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.override(200,200).placeholder(R.drawable.logoback)
.into(menuViewHolder.vImage);
setFadeAnimation(menuViewHolder,i);
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
#Override
public ImageAdapter.MenuViewHolder onCreateViewHolder(ViewGroup
viewGroup, int i) {
final View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.activity_gallery_enter, viewGroup, false);
return new ImageAdapter.MenuViewHolder(itemView);
}
#Override
public void onViewDetachedFromWindow(ImageAdapter.MenuViewHolder holder)
{
((ImageAdapter.MenuViewHolder)holder).itemView.clearAnimation();
}
public class MenuViewHolder extends RecyclerView.ViewHolder{
protected ImageView vImage;
public MenuViewHolder(View v) {
super(v);
vImage = (ImageView) v.findViewById(R.id.iv_photoGallety);
}
}
private void setFadeAnimation(ImageAdapter.MenuViewHolder view, int
position) {
if (position > lastPosition) {
AlphaAnimation anim = new AlphaAnimation(0.0f, 2.0f);
anim.setDuration(1000);
view.itemView.startAnimation(anim);
lastPosition = position;
}
}
}
ImageDetailActivity.java
public class imageDetailActivity extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
public ArrayList<ImageGallery> data = new ArrayList<>();
int pos;
Toolbar aboveToolbar;
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_detail);
//aboveToolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.detail_toolbar);
//setSupportActionBar(aboveToolbar);
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
data = getIntent().getParcelableArrayListExtra("data");
pos = getIntent().getIntExtra("pos", 0);
setTitle(data.get(pos).getName());
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(), data);
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setPageTransformer(true, new DepthPageTransformer());
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setCurrentItem(pos);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
//noinspection ConstantConditions
setTitle(data.get(position).getName());
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public ArrayList<ImageGallery> data = new ArrayList<>();
public SectionsPagerAdapter(FragmentManager fm, ArrayList<ImageGallery> data) {
super(fm);
this.data = data;
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position, data.get(position).getName(), data.get(position).getUrl());
}
#Override
public int getCount() {
// Show 3 total pages.
return data.size();
}
// #Override
//public CharSequence getPageTitle(int position) {
//return data.get(position).getName();
// }
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
String name, url;
ImageView ImageView;
int pos;
private static final String ARG_SECTION_NUMBER = "section_number";
//private static final String ARG_IMG_TITLE = "image_title";
private static final String ARG_IMG_URL = "image_url";
#Override
public void setArguments(Bundle args) {
super.setArguments(args);
this.pos = args.getInt(ARG_SECTION_NUMBER);
//this.name = args.getString(ARG_IMG_TITLE);
this.url = args.getString(ARG_IMG_URL);
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber, String name, String url) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
//args.putString(ARG_IMG_TITLE, name);
args.putString(ARG_IMG_URL, url);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_image_detail, container, false);
this.ImageView = (ImageView) rootView.findViewById(R.id.detail_image);
Glide.with(getActivity()).load(url).thumbnail(0.1f).crossFade()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.override(200,200).placeholder(R.drawable.tiara3)
.into(this.ImageView);
return rootView;
}
}
}
error log:
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:501)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:354)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
at android.content.res.Resources.loadDrawable(Resources.java:1970)
at android.content.res.Resources.getDrawable(Resources.java:660)
at com.bumptech.glide.request.GenericRequest.getPlaceholderDrawable(GenericRequest.java:416)
at com.bumptech.glide.request.GenericRequest.clear(GenericRequest.java:323)
at com.bumptech.glide.request.ThumbnailRequestCoordinator.clear(ThumbnailRequestCoordinator.java:106)
at com.bumptech.glide.manager.RequestTracker.clearRequests(RequestTracker.java:94)
at com.bumptech.glide.RequestManager.onDestroy(RequestManager.java:221)
at com.bumptech.glide.manager.ActivityFragmentLifecycle.onDestroy(ActivityFragmentLifecycle.java:64)
at com.bumptech.glide.manager.SupportRequestManagerFragment.onDestroy(SupportRequestManagerFragment.java:147)
at android.support.v4.app.Fragment.performDestroy(Fragment.java:2322)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1240)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1272)
at android.support.v4.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:2186)
at android.support.v4.app.FragmentController.dispatchDestroy(FragmentController.java:271)
at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:388)
at android.support.v7.app.AppCompatActivity.onDestroy(AppCompatActivity.java:209)
at android.app.Activity.performDestroy(Activity.java:5273)
at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1110)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3438)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3469)
at android.app.ActivityThread.access$1200(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1287)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
real device result:
enter image description here
smulator result:
enter image description here
Add below line in Application tag in Menifest file:
android:largeHeap="true"
Please I have been trying to display json data from recycler view to another activity but only the textview displays and the image does not. This is my code
public class MainActivity extends AppCompatActivity {
public String content;
public static MainActivity parse(JSONObject object){
MainActivity post=new MainActivity();
post.content = Html.fromHtml(object.optString("content")).toString();
return post;
}
ImageView thumbnail;
TextView title;
private static final String TAG = "RecyclerViewExample";
private SwipeRefreshLayout swipeRefreshLayout;
private List<FeedItem> feedsList;
private RecyclerView mRecyclerView;
private MyRecyclerAdapter adapter;
private ProgressBar progressBar;
public MainActivity(){
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feed_list);
// Initialize recycler view
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
progressBar.setVisibility(View.VISIBLE);
// Downloading data from below url
final String url = "http://street2view.com/api/get_recent_posts/";
new AsyncHttpTask().execute(url);
}
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
setProgressBarIndeterminateVisibility(true);
}
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
// 200 represents HTTP OK
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
// Download complete. Let us update UI
progressBar.setVisibility(View.GONE);
if (result == 1) {
adapter = new MyRecyclerAdapter(MainActivity.this, feedsList);
mRecyclerView.setAdapter(adapter);
} else {
Toast.makeText(MainActivity.this, "Check Your Internet Connection", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (item.getItemId() == R.id.about) {
Intent settingsActivityIntent = new Intent();
settingsActivityIntent.setClass(this, AboutActivity.class);
this.startActivityForResult(settingsActivityIntent, 111);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
new AlertDialog.Builder(this)
.setTitle("Quit")
.setMessage("Do you wish to exit the app?")
.setCancelable(false)
.setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
}).create().show();
}
public String stripHtmlTags(String html) {
return Html.fromHtml(html).toString();
}
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray posts = response.optJSONArray("posts");
feedsList = new ArrayList<>();
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
FeedItem item = new FeedItem();
item.setTitle(post.optString("title"));
item.setContent(post.optString("content"));
item.setdate(post.optString("date"));
JSONArray attachments = post.getJSONArray("attachments");
if (null != attachments && attachments.length() > 0) {
JSONObject attachment = attachments.getJSONObject(0);
if (attachment != null)
item.setAttachmentUrl(attachment.getString("url"));
}
JSONArray categories = post.getJSONArray("categories");
if (null != categories && categories.length() > 0) {
JSONObject attachment = categories.getJSONObject(0);
if (categories != null)
item.setCategories(attachment.getString("title"));
}
feedsList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
and this is the adapter class in which i use to send the data from the recycler view to the second activity
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.CustomViewHolder> {
private List<FeedItem> feedItemList;
private Context mContext;
public MyRecyclerAdapter(Context context, List<FeedItem> feedItemList) {
this.feedItemList = feedItemList;
this.mContext = context;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, null);
CustomViewHolder viewHolder = new CustomViewHolder(view,mContext, (ArrayList<FeedItem>) feedItemList);
return viewHolder;
}
#Override
public void onBindViewHolder(CustomViewHolder customViewHolder, int i) {
FeedItem feedItem = feedItemList.get(i);
//Download image using picasso library
Glide.with(mContext).load(feedItem.getAttachmentUrl())
.error(R.color.list_item_title)
.placeholder(R.color.list_item_title)
.into(customViewHolder.imageView);
//Setting text view title
customViewHolder.textView.setText((feedItem.getTitle()));
customViewHolder.textView2.setText(feedItem.getdate());
customViewHolder.categories.setText(feedItem.getCategories());
}
#Override
public int getItemCount() {
return (null != feedItemList ? feedItemList.size() : 0);
}
public class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected ImageView imageView;
protected TextView textView2;
protected TextView textView;
protected TextView content;
protected TextView categories;
public RelativeLayout relativeLayout;
ArrayList<FeedItem> feeditem = new ArrayList<FeedItem>();
Context ctx;
public CustomViewHolder(View view, Context ctx, ArrayList<FeedItem> feeditem) {
super(view);
view.setOnClickListener(this);
this.ctx = ctx;
this.feeditem = feeditem;
this.imageView = (ImageView) view.findViewById(R.id.thumbnail);
this.textView2 = (TextView) view.findViewById(R.id.date);
this.categories = (TextView) view.findViewById(R.id.categories);
this.textView = (TextView) view.findViewById(R.id.title);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
FeedItem feeditem = this.feeditem.get(position);
Intent intent = new Intent(this.ctx,Main2Activity.class);
intent.putExtra("title",feeditem.getTitle());
intent.putExtra("content",feeditem.getContent());
Html.fromHtml(String.valueOf(intent.putExtra("content",feeditem.getContent()))).toString();
intent.putExtra("thumbnail",feeditem.getAttachmentUrl());
this.ctx.startActivity(intent);
}
}
}
and this is the second activity where i want to display the json data (when i run the application the textview shows but the imageview dosent thanks in advance)
public class Main2Activity extends AppCompatActivity {
ImageView imageView;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
imageView = (ImageView)findViewById(R.id.contentImage);
textView = (TextView)findViewById(R.id.title2);
textView.setText(getIntent().getStringExtra("title"));
imageView.setImageResource(getIntent().getIntExtra("thumbnail", 00));
}}
You can try this
public class Main2Activity extends AppCompatActivity {
ImageView imageView;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
imageView = (ImageView) findViewById(R.id.contentImage);
textView = (TextView) findViewById(R.id.title2);
String title = getIntent().getStringExtra("title");
String thumbnail = getIntent().getStringExtra("thumbnail");
textView.setText(title);
// set image here
Glide.with(this).load(thumbnail)
.into(imageView);
}
}
I have implemented GridView in Android.
The first fragment use AsyncTask to load the file and show on the GridView. When the getView has been call. It will call ExtractThumbnail to read the thumbnail. It works fine.
And it can turn to second fragment via a button.
I click the button and turn to second fragment , when the ExtractThumbnail is reading the thumbnail of video and photo.
It crashes due to java.lang.NullPointerException.
The code of first fragment is like the following:(I have omitted some code that are not important)
public class LocalFileBrowserFragment extends Fragment implements MultiChoiceModeListener{
public static Executor threadpoolexecutor;
public static Activity activity;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mFileListAdapter = new LocalFileListAdapter(inflater, mFileList) ;
mFileListAdapter.GridAdapter(getActivity());
activity = getActivity();
loadfilelistTask = new LoadFileListTask();
new LoadFileListTask().executeOnExecutor(threadpoolexecutor) ;
BackButton = (ImageButton) view.findViewById(R.id.BackButton);
BackButton.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
loadfilelistTask.cancel(true);
Checkurl task = new Checkurl(activity, LocalFileBrowserFragment.this);
task.execute();
}
});
}
public class LocalFileListAdapter extends BaseAdapter {
private LayoutInflater mInflater ;
private ArrayList<FileNode> mFileList ;
private static final String TAG = "LocalFileBrowserFragment" ;
private Context mContext;
public LocalFileListAdapter(LayoutInflater inflater, ArrayList<FileNode> fileList) {
mInflater = inflater ;
mFileList = fileList ;
}
public void GridAdapter(Context ctx) {
// TODO Auto-generated method stub
mContext = ctx;
}
private List<ExtractThumbnail> thumbnailTaskList = new LinkedList<ExtractThumbnail>();
private class ExtractThumbnail extends AsyncTask<ViewTag, Integer, Bitmap> {
//Read the Thumbnail.
ViewTag mViewTag;
#Override
protected void onPreExecute() {
thumbnailTaskList.add(this);
super.onPreExecute();
}
#Override
protected Bitmap doInBackground(ViewTag... params) {
mViewTag = params[0];
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inDither = false;
options.inScaled = false;
BitmapFactory.decodeFile(mViewTag.mFileNode.mName, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
int requestedHeight = 64;
int requestedWidth = 64;
int scaleDownFactor = 0;
options.inJustDecodeBounds = false;
while (true) {
scaleDownFactor++;
if (imageHeight / scaleDownFactor <= requestedHeight
|| imageWidth / scaleDownFactor <= requestedWidth) {
scaleDownFactor--;
break;
}
}
options.inSampleSize = scaleDownFactor;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
float scaleFactor = (float) requestedHeight / imageHeight;
scaleFactor = Math.max(scaleFactor, (float) requestedWidth
/ imageWidth);
Bitmap originalBitmap = BitmapFactory.decodeFile(
mViewTag.mFileNode.mName, options);
if (originalBitmap == null) {
try {
byte[] data = Util.getLibVlcInstance().getThumbnail(
"file://" + mViewTag.mFileNode.mName,
requestedWidth, requestedHeight);
if (data != null) {
Bitmap thumbnail = Bitmap.createBitmap(requestedWidth,
requestedHeight, Bitmap.Config.ARGB_8888);
thumbnail.copyPixelsFromBuffer(ByteBuffer.wrap(data));
thumbnail = Util.cropBorders(thumbnail, requestedWidth,
requestedHeight);
return thumbnail;
}
} catch (LibVlcException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Bitmap thumbnail = ThumbnailUtils.extractThumbnail(originalBitmap,
requestedWidth, requestedHeight);
originalBitmap.recycle();
return thumbnail;
}
#Override
protected void onPostExecute(Bitmap thumbnail) {
Log.i(TAG, "thumbnail = " + thumbnail);
if (thumbnail != null) {
mViewTag.mThumbnail.setImageBitmap(thumbnail);
}
thumbnailTaskList.remove(this);
mViewTag.mThumbnailTask = null;
super.onPostExecute(thumbnail);
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewTag viewTag ;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.filelist_row, null) ;
viewTag = new ViewTag(mContext , (ImageView) convertView.findViewById(R.id.fileListThumbnail);
convertView.setTag(viewTag) ;
}
//Read the Thumbnail.
viewTag.mThumbnailTask = new ExtractThumbnail() ;
viewTag.mThumbnailTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, viewTag) ;
return convertView ;
}
}
And I create a class , When I click the button at first , it call Checkurl task = new Checkurl(activity, LocalFileBrowserFragment.this);.
The code of Checkurl class is like the following(I have omitted some code that are not important):
public class Checkurl extends AsyncTask<URL, Integer, String>{
Context context;
Fragment current_frag;
public Checkurl(Context contextin , Fragment frag)
{
context = contextin;
current_frag = frag;
// The current_frag.getActivity here is not null
}
#Override
protected String doInBackground(URL... params) {
// TODO Auto-generated method stub
URL url = CameraCommand.commandQueryAV1Url() ;
if (url != null) {
return CameraCommand.sendRequest(url) ;
}
return null ;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
Fragment newFragment = StreamPlayerFragment.newInstance(liveStreamUrl) ;
FragmentManager fragmentManager = current_frag.getActivity().getFragmentManager() ;
// But the current_frag.getActivity here is null. So it crash here.
if (fragmentManager.getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry backEntry = fragmentManager.getBackStackEntryAt(fragmentManager
.getBackStackEntryCount() - 1) ;
if (backEntry != null && backEntry.getName().equals(newFragment.getClass().getName()))
return ;
}
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction() ;
fragmentTransaction
.setCustomAnimations(R.anim.right_in, R.anim.right_out, R.anim.left_in, R.anim.left_out)
.replace(R.id.mainMainFragmentLayout, newFragment)
.addToBackStack(newFragment.getClass().getName()).commit() ;
fragmentManager.executePendingTransactions() ;
super.onPostExecute(result) ;
}
}
When the ExtractThumbnail AsyncTask is reading Thumbnail and not reading finish.
I click the button turn to second fragment.
It call Checkurl task = new Checkurl(activity, LocalFileBrowserFragment.this);.
But it always crash at FragmentManager fragmentManager = originalFragment.getActivity().getFragmentManager(); in Checkurl class.
I try to print originalFragment.getActivity() in the log. It show originalFragment.getActivity() is null.
Why the originalFragment.getActivity() is null ?
Thanks in advance.
Your AsyncTask should look like this:
Activity context;
public Checkurl(Activity contextin){
context = contextin;
}
protected void onPostExecute(String result) {
//etc
FragmentManager fragmentManager = context.getFragmentManager() ;
}
Your calling originalFragment.getActivity() is null because your fragment is detached from activity (and you switch to new fragment) when you do task in background.
Also, do not depend on current fragment in your AsyncTask because it may be destroyed when you move to new fragment (it may cause NullPointerException)
try to keep activity reference when onAttach is called and use the activity reference wherever needed, for e.g.
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mActivity = activity;
}
You shouldn't use getActivity to retrieve it. Override void onAttach(Activity activity) in your fragments and save the argument reference to the activity in a member variable.
I am trying to fetch a list of photos from a photo set in flickr
using universal image loader
My Base Activity ImagePagerActivity calls FetchPhotos which extends Async Task.
Code Follows
public class ImagePagerActivity extends BaseActivity {
private static final String STATE_POSITION = "STATE_POSITION";
public static final String API_KEY="mykey";
public static final String USER_ID="myid";
DisplayImageOptions options;
private Photos thePhotoList;
ViewPager pager;
private String thePhotos="";
private final int[] timeout={3,10};
private String url="http://www.flickr.com/services/rest/?method=flickr.photosets.getPhotos&format=json&api_key="+API_KEY+"&photoset_id=111111111";
private String[] imageUrls;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_image_pager);
Bundle bundle = getIntent().getExtras();
String url="http://www.flickr.com/services/rest/?method=flickr.photosets.getPhotos&format=json&api_key="+API_KEY+"&photoset_id=72157633359614452";
setContentView(R.layout.pics);
try{
((ViewAnimator)findViewById(R.id.PictureAnimator)).removeAllViews();
}catch (Exception e) {}
thePhotoList = new Photos(url);
thePhotoList.execute();
imageUrls=thePhotoList.imageList;
//imageUrls = bundle.getStringArray(Extra.IMAGES);
int pagerPosition = bundle.getInt(Extra.IMAGE_POSITION, 0);
if (savedInstanceState != null) {
pagerPosition = savedInstanceState.getInt(STATE_POSITION);
}
options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.resetViewBeforeLoading()
.cacheOnDisc()
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.displayer(new FadeInBitmapDisplayer(300))
.build();
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new ImagePagerAdapter(this.imageUrls));
pager.setCurrentItem(pagerPosition);
}
private class Photos extends com.flickr.FetchPhotos{
#Override
public void onFetchError() {}
public Photos(String url) {super(ImagePagerActivity.this, url);}
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(STATE_POSITION, pager.getCurrentItem());
}
private class ImagePagerAdapter extends PagerAdapter {
private String[] images;
private LayoutInflater inflater;
ImagePagerAdapter(String[] images) {
this.images = images;
inflater = getLayoutInflater();
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
#Override
public void finishUpdate(View container) {
}
#Override
public int getCount() {
return images.length;
}
#Override
public Object instantiateItem(ViewGroup view, int position) {
View imageLayout = inflater.inflate(R.layout.item_pager_image, view, false);
ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image);
final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading);
imageLoader.displayImage(images[position], imageView, options, new SimpleImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
spinner.setVisibility(View.VISIBLE);
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
String message = null;
switch (failReason.getType()) {
case IO_ERROR:
message = "Input/Output error";
break;
case DECODING_ERROR:
message = "Image can't be decoded";
break;
case NETWORK_DENIED:
message = "Downloads are denied";
break;
case OUT_OF_MEMORY:
message = "Out Of Memory error";
break;
case UNKNOWN:
message = "Unknown error";
break;
}
Toast.makeText(ImagePagerActivity.this, message, Toast.LENGTH_SHORT).show();
spinner.setVisibility(View.GONE);
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
spinner.setVisibility(View.GONE);
}
});
((ViewPager) 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;
}
#Override
public void startUpdate(View container) {
}
}
}
next is the FetchPhotos class
public abstract class FetchPhotos extends AsyncTask<Void, Void, Boolean>{
private Context context;
private ProgressDialog pd;
private String thePhotos="";
private String url;
private final int[] timeout={3,10};
public ArrayList<PictureInfo> thePics;
public String[] imageList;
public FetchPhotos(Context context,String url) {
this.context=context;
this.url=url;
}
public String[] fillGalery(JSONObject theFeed) {
// TODO Auto-generated method stub
String[] imageUrls = null;
try{
JSONArray Categories=theFeed.getJSONArray("photo");
imageUrls=new String[Categories.length()];
for (int i=0;i<(Categories.length()>15?15:Categories.length());i++){
JSONObject pic = Categories.getJSONObject(i);
String url1="http://farm"+pic.getString("farm")+".staticflickr.com/"+pic.getString("server")+"/"+
pic.getString("id")+"_"+pic.getString("secret")+".jpg";
imageUrls[i]=url1;
System.out.println(imageUrls[i]);
}
return imageUrls;
}
catch(Exception e){
}
return imageUrls;
}
#Override
protected void onPreExecute() {
pd=ProgressDialog.show(context, "downloading", "please wait");
super.onPreExecute();
}
#Override
protected Boolean doInBackground(Void... arg0) {
try{
thePhotos = new Internet().GetRequest(url, null, timeout);
return true;
}catch (Exception e) {
return false;
}
}
#Override
protected void onPostExecute(Boolean result) {
pd.dismiss();
if(result){
try {
thePhotos=thePhotos.split("\\(")[1];
thePhotos.replace("\\)", "");
imageList=fillGalery(new JSONObject(thePhotos).getJSONObject("photoset"));
} catch (Exception e) {Log.e("karp", "photolist2: "+e.getMessage());onFetchError();onFetchError();}
}else{
onFetchError();
}
super.onPostExecute(result);
}
public abstract void onFetchError();
public void LoadPhoto(PictureInfo pi){
Log.d("karp", "LoadPhoto");
if(!(pi.executed)){
new LoadPics(pi).execute();
pi.executed=true;
}
}
private class LoadPics extends RemoteImage{
private ImageView ivTarget;
private ProgressBar pb;
public LoadPics(PictureInfo pi) {
super(pi.url);
this.ivTarget=pi.iv;
this.pb=pi.pb;
}
#Override
public void onSuccess(Bitmap remoteBitmap) {
try{
pb.setVisibility(View.INVISIBLE);
ivTarget.setImageBitmap(remoteBitmap);
}catch (Exception e) {}
}
#Override
public void onFail() {pb.setVisibility(View.INVISIBLE);}
}
}
I have created Photos class in Image Pager
and then Im trying to access fill gallery
Now Im trying to fill a string array with the image urls from flickr
using the method fillGallery that reurns a string array
In my base activity im calling
thePhotoList = new Photos(url);
thePhotoList.execute();
imageUrls=thePhotoList.imageList;
but try as i may i cant get an array in imageUrls which is a String Array.
When i use a hard coded string array with urls for images in it, the code works.
Any help would be really appreciated.
Im sure im doing something very silly as I am new to this.
Many thanks . Cheers!
I got it to work . Needed to add a listener interface , call the method from onPostExecute,
Implement it in the activity, access the variable in the implementation of the listeners abstract method. Should have researched a bit more before posting,but was stuck with the problem too long . Apologies.