Android uses GridView to load (weak reference) network pictures asynchronously (click to view)

Posted by VirtuosiMedia on Tue, 02 Jun 2020 17:57:27 +0200

Android uses GridView to load (weak reference) network pictures asynchronously (click to view)

In the current Android development, more and more app s use the album function of Android. Using the album will use GridView to load pictures, but when loading a large number of pictures, there will be a black screen because the loading process is slow, and because more and more pictures cause the problem of OOM. In this case, you need to use threads to load images and display them asynchronously.

First look at the renderings:

  • **
  • A GridView control
  • Adapter
  • A custom class loaded asynchronously
  • A dialog to load the original image
  • **

activity_mail.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="activity.cc.com.demo014.MainActivity"
    android:orientation="vertical">

    <GridView
        android:id="@+id/gridview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="3"/>

</LinearLayout>
Note: only one GridView control is included

MainActivity.java:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        //Get control and implement click event
        gridView = (GridView) findViewById(R.id.gridview);
        gridView.setOnItemClickListener(this);

        //The GetData method is to populate the data
        getDatas();


        //Using adapter to fill in data
        gridViewAdapter = new GridViewAdapter(this, datas, gridView);
        gridView.setAdapter(gridViewAdapter);

    }

GridViewAdapter.java:

package activity.cc.com.demo014;

import android.app.Activity;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by admin on 2017/12/11.
 */

public class GridViewAdapter extends BaseAdapter {

    List<GridViewData> datas = new ArrayList<GridViewData>();

    GridView gridview;

    Activity activity;

    LayoutInflater inflater;

    AsyncImageLoader asyncImageLoader;

    /**
     * Instantiate adapter and receive the passed data
     * @param activity
     * @param datas
     * @param gridview
     */
    public GridViewAdapter(Activity activity, List<GridViewData> datas, GridView gridview){
        this.activity = activity;
        this.datas = datas;
        this.gridview = gridview;

        //Instantiate layoutinflate
        inflater = activity.getLayoutInflater();
        //Instantiate a class that loads pictures asynchronously
        asyncImageLoader = new AsyncImageLoader();
    }

    /**
     * This method is to display the number of pictures
     * @return Depends on the size of the data
     */
    @Override
    public int getCount() {
        return datas.size();
    }

    /**
     * Get the data of each item
     * @param position
     * @return
     */
    @Override
    public GridViewData getItem(int position) {
        return datas.get(position);
    }

    /**
     * getItemId
     * @param position
     * @return
     */
    @Override
    public long getItemId(int position) {
        return position;
    }

    /**
     * One system call per load
     * @param position
     * @param convertView
     * @param parent
     * @return
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        //When the recycled view is empty, get it again
        if(convertView == null){
            convertView = inflater.inflate(R.layout.gridview_item, null);
        }
        convertView.setTag(position);
        //Get the value of each item
        GridViewData info = getItem(position);

        //Using class of asynchronous loading picture to load picture and implement callback
        asyncImageLoader.loadDrawable(position, info.img_url, new AsyncImageLoader.ImageCallback() {
            @Override
            public void onImageLoad(Integer t, Bitmap bitmap) {
                View view = gridview.findViewWithTag(t);
                if(view != null){
                    Log.i("TAG", "Loading succeeded...");
                    ImageView img_url = view.findViewById(R.id.img_url);
                    img_url.setImageBitmap(bitmap);
                }
            }

            @Override
            public void onError(Integer t) {
                View view = gridview.findViewWithTag(t);
                if(view != null){
                    Log.i("TAG", "Load failed...");
                    ImageView img_url = view.findViewById(R.id.img_url);
                    //Loading or failed to load. The app icon is loaded by default
                    img_url.setBackgroundResource(R.mipmap.ic_launcher);
                }
            }
        });

        TextView txt_name = convertView.findViewById(R.id.txt_name);
        txt_name.setText(info.name);

        return convertView;
    }
}

GridViewData.java:

package activity.cc.com.demo014;

/**
 * Created by admin on 2017/12/11.
 */

public class GridViewData {

    public GridViewData(String img_url, String name){
        this.img_url = img_url;
        this.name = name;
    }

    public String img_url, name;

    public String getImg_url() {
        return img_url;
    }

    public void setImg_url(String img_url) {
        this.img_url = img_url;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "GridViewData{" +
                "img_url='" + img_url + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
Note: note that the attribute value is public. The asynchronous loading of pictures is over here. Next, click the image to view the original image.

MainActivity.java:

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    Log.i("TAG", "" + position);
    showImageDialog(position);
}

private void showImageDialog(int position) {
    //A friendly prompt box will pop up, prompting the user to confirm to log out?
    new CommomDialog(this, position, R.style.dialog, datas.get(position).getImg_url(), new CommomDialog.OnCloseListener() {
        @Override
        public void onClick(Dialog dialog, boolean confirm) {
            if(confirm){
                dialog.dismiss();
            }
        }
    }).setTitle(datas.get(position).getName()).show();
}

CommomDialog.java:

package activity.cc.com.demo014;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Encapsulated dialog
 */
public class CommomDialog extends Dialog implements View.OnClickListener {

    private TextView textview_name;
    private ImageView image_url;

    private Context mContext;
    private String img_url;
    private OnCloseListener listener;
    private String positiveName;
    private String negativeName;
    private String title;

    int position;

    AsyncImageLoader asyncImageLoader;

    public CommomDialog(Context context) {
        super(context);
        this.mContext = context;
    }

    public CommomDialog(Context context, int themeResId, String img_url) {
        super(context, themeResId);
        this.mContext = context;
        this.img_url = img_url;
    }

    public CommomDialog(Context context, int position, int themeResId, String img_url, OnCloseListener listener) {
        super(context, themeResId);
        this.mContext = context;
        this.position = position;
        this.img_url = img_url;
        this.listener = listener;

        asyncImageLoader = new AsyncImageLoader();
    }

    protected CommomDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
        super(context, cancelable, cancelListener);
        this.mContext = context;
    }

    public CommomDialog setTitle(String title){
        this.title = title;
        return this;
    }

    public CommomDialog setPositiveButton(String name){
        this.positiveName = name;
        return this;
    }

    public CommomDialog setNegativeButton(String name){
        this.negativeName = name;
        return this;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.imgae_view);
        setCanceledOnTouchOutside(false);
        initView();
        initData();
    }

    private void initData() {
        asyncImageLoader.loadDrawable(position, img_url, new AsyncImageLoader.ImageCallback() {
            @Override
            public void onImageLoad(Integer t, Bitmap bitmap) {
                image_url.setImageBitmap(bitmap);
            }

            @Override
            public void onError(Integer t) {
                image_url.setBackgroundResource(R.mipmap.ic_launcher);
            }
        });

        textview_name.setText(title);
    }

    private void initView(){
        image_url = findViewById(R.id.image_url);
        textview_name = findViewById(R.id.textview_name);

        image_url.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int temdId = v.getId();
        if(temdId == R.id.image_url){
            dismiss();
        }
//        switch (v.getId()){
//            case R.id.cancel:
//                if(listener != null){
//                    listener.onClick(this, false);
//                }
//                this.dismiss();
//                break;
//            case R.id.submit:
//                if(listener != null){
//                    listener.onClick(this, true);
//                }
//                break;
//        }
    }

    public interface OnCloseListener{
        void onClick(Dialog dialog, boolean confirm);
    }
}

imgae_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF" >

    <TextView
        android:id="@+id/textview_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="TextView"
        android:textColor="#000000" />

    <ImageView
        android:id="@+id/image_url"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:srcCompat="@mipmap/ic_launcher" />

</LinearLayout>
Note: so far, the function has been realized.

Optimization: the image shown here is displayed according to the original size. If you need to fix the size and fill the layout, add android:scaleType= ”fitXY "this line of code is good.

GAME OVER!!!

Click to download the source code

CSDN doesn't seem to have the option to download resources for free. So, if you need source code and no points, please leave a message

Topics: Android Java xml encoding