【问题标题】:How to load GridView images with AsyncTask?如何使用 AsyncTask 加载 GridView 图像?
【发布时间】:2015-11-19 14:55:55
【问题描述】:

我有,在下面的片段下面,它用来自 URL 的位图填充了一个网格视图。问题是我知道这是非常“繁重”的工作,并且是在 UI 线程上完成的,因此在加载网格时会减慢片段的速度。

我读到需要 AsyncTask 来在后台执行“繁重”工作,但我找不到任何似乎符合我想要的东西。

public class HomeFragment extends Fragment {

protected static final String TAG = null;
public HomeFragment(){}
GridView gridView;
private GridViewAdapter gridAdapter;
private SQLiteHandler db;
private SwipeRefreshLayout swipeLayout;
private ProgressDialog pDialog;

GPSTracker gps;
String uid;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    db = new SQLiteHandler(getActivity());
    gridAdapter = new GridViewAdapter(getActivity(), R.layout.grid_item_layout, getData());


    pDialog = new ProgressDialog(getActivity());
    pDialog.setCancelable(true);

    uid="1";
    String email = db.getFromTable(getActivity(), "email", SQLiteHandler.TABLE_LOGIN, "WHERE _id="+uid);
    String from_age = db.getFromTable(getActivity(), "from_age", SQLiteHandler.TABLE_SETTINGS, "WHERE uid="+uid);
    String to_age = db.getFromTable(getActivity(), "to_age", SQLiteHandler.TABLE_SETTINGS, "WHERE uid="+uid);
    String distance = db.getFromTable(getActivity(), "distance", SQLiteHandler.TABLE_SETTINGS, "WHERE uid="+uid);
    String unit = db.getFromTable(getActivity(), "unit", SQLiteHandler.TABLE_SETTINGS, "WHERE uid="+uid);
    String men = db.getFromTable(getActivity(), "men", SQLiteHandler.TABLE_SETTINGS, "WHERE uid="+uid);
    String women = db.getFromTable(getActivity(), "women", SQLiteHandler.TABLE_SETTINGS, "WHERE uid="+uid);

    fetchUsers(email, from_age, to_age, distance, unit,  men, women);

    final View rootView = inflater.inflate(R.layout.fragment_home, container, false);


    //getActivity().getActionBar().setTitle(R.string.home);

    gridView = (GridView) rootView.findViewById(R.id.gridView);


    gridView.setAdapter(gridAdapter);

    gridView.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            ImageItem item = (ImageItem) parent.getItemAtPosition(position);
            ImageView imageView = (ImageView) v.findViewById(R.id.image);
            //Create intent
            Intent intent = new Intent(getActivity(), DetailsActivity.class);
            int[] screenLocation = new int[2];
            imageView.getLocationOnScreen(screenLocation);
            intent.putExtra("left", screenLocation[0]).
            putExtra("top", screenLocation[1]).
            putExtra("width", imageView.getWidth()).
            putExtra("height", imageView.getHeight()).
            putExtra("uid", item.getUid());
            startActivity(intent);
        }
    });
    swipeLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
    swipeLayout.setOnRefreshListener(new OnRefreshListener() {

        @Override
        public void onRefresh() {
            //my update process
            Fragment currentFragment = getFragmentManager().findFragmentByTag("0");
            FragmentTransaction fragTransaction = getFragmentManager().beginTransaction();
            fragTransaction.detach(currentFragment); 
            fragTransaction.attach(currentFragment); 
            fragTransaction.commit(); 
        }
    });

    return rootView;
}

 // Prepare some dummy data for gridview
private ArrayList<ImageItem> getData() {
    final ArrayList<ImageItem> imageItems = new ArrayList<>();

    Cursor cursor = db.getAllRows("*", SQLiteHandler.TABLE_USERS, "");
    //Query local DB to initialize settings screen

    for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()){
        String uid = cursor.getString(cursor.getColumnIndex(SQLiteHandler.KEY_UID));
        String name = cursor.getString(cursor.getColumnIndex(SQLiteHandler.KEY_NAME));
        String dob = cursor.getString(cursor.getColumnIndex(SQLiteHandler.KEY_DOB));
        //String gender = cursor.getString(cursor.getColumnIndex(SQLiteHandler.KEY_GENDER));
        String photourl = cursor.getString(cursor.getColumnIndex(SQLiteHandler.KEY_PHOTOURL));
        //String distance = cursor.getString(cursor.getColumnIndex(SQLiteHandler.KEY_DISTANCE));

        String[] birthdayArr = dob.split("-");

        int age = getAge(Integer.parseInt(birthdayArr[0]), Integer.parseInt(birthdayArr[1]), Integer.parseInt(birthdayArr[2]));

        Bitmap bitmap = getBitmapFromURL(photourl);

        imageItems.add(new ImageItem(bitmap, name+" - " + age, uid));
    }
    return imageItems;
}


public static Bitmap getBitmapFromURL(String src) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

    StrictMode.setThreadPolicy(policy); 
    try { 
        URL url = new URL(src);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        return myBitmap;
    } catch (IOException e) {
        // Log exception 
        return null; 
    } 
} 

public int getAge(int year, int month, int day) {
    //int nowMonth = now.getMonth()+1;
    int nowMonth = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
    //int nowYear = now.getYear()+1900;
    int nowYear = Calendar.getInstance().get(Calendar.YEAR);
    int result = nowYear - year;

    if (month > nowMonth) {
        result--;
    }
    else if (month == nowMonth) {
        int nowDay = Calendar.getInstance().get(Calendar.DATE);

        if (day > nowDay) {
            result--;
        }
    }
    return result;
}

private void showDialog() {
    if (!pDialog.isShowing())
        pDialog.show();
}

private void hideDialog() {
    Log.i("hideDialog",  "called");
    if (pDialog.isShowing())
        pDialog.dismiss();
}

public void fetchUsers(final String email, final String agefrom, final String ageto, final String distance, final String distanceUnit, final String interested_men, final String interested_wmen){
    // Tag used to cancel the request

    gps = new GPSTracker(getActivity());
    String tag_string_req = "req_login";
    pDialog.setMessage("Finding users ...");
    showDialog();

    StringRequest strReq = new StringRequest(Method.POST,
            AppConfig.URL_LOGIN, new Response.Listener<String>() {

                @Override
                public void onResponse(String response) {
                    Log.d(TAG, "Fetch Response: " + response.toString());
                    hideDialog();
                    try {
                        JSONObject jObj = new JSONObject(response);
                        int success = jObj.getInt("success");
                        JSONArray users = jObj.getJSONArray("users");

                        // Check for error node in json
                        if (success == 1) {

                            //Log.i("success", users+"");

                            if (users.length() == 0) {
                               Toast.makeText(getActivity(), "No users found! \nPlease try again soon.", Toast.LENGTH_LONG).show(); 
                               db.emptyTable(SQLiteHandler.TABLE_USERS);
                            }else{
                                db.emptyTable(SQLiteHandler.TABLE_USERS);
                                for (int i = 0; i < users.length(); i++) {
                                    JSONObject user = users.getJSONObject(i);
                                    String uid = user.getString("uid");
                                    String name = user.getString("name");
                                    String dob = user.getString("dob");
                                    String gender = user.getString("gender");
                                    String photourl = user.getString("photoUrl");
                                    String distance = user.getString("distance");

                                    String[][] userValues = {   
                                            { SQLiteHandler.KEY_UID, uid},
                                            { SQLiteHandler.KEY_NAME, name},
                                            { SQLiteHandler.KEY_DOB, dob},
                                            { SQLiteHandler.KEY_GENDER, gender},
                                            { SQLiteHandler.KEY_PHOTOURL, photourl},
                                            { SQLiteHandler.KEY_DISTANCE, distance}
                                    };
                                    db.insert(SQLiteHandler.TABLE_USERS, userValues);
                                } 
                            }
                        } else {
                            // Error in login. Get the error message
                            String errorMsg = jObj.getString("error_msg");
                            Toast.makeText(getActivity(),errorMsg, Toast.LENGTH_LONG).show();
                        }
                    } catch (JSONException e) {
                        // JSON error
                        e.printStackTrace();
                    }

                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e(TAG, "Login Error: " + error.getMessage());
                    Toast.makeText(getActivity(),
                            error.getMessage(), Toast.LENGTH_LONG).show();
                    hideDialog();
                }
            }) {

        @Override
        protected Map<String, String> getParams() {
            // Posting parameters to login url
            //$lat, $lng, $email, $agefrom, $ageto, $distance, $distanceUnit, $interested_men, $interested_wmen
            Map<String, String> params = new HashMap<String, String>();
            params.put("tag", "login");
            params.put("lat", gps.getLatitude()+"");
            params.put("lng", gps.getLongitude()+"");
            params.put("email", email);
            params.put("agefrom", agefrom);
            params.put("ageto", ageto);
            params.put("distance", distance);
            params.put("distanceUnit", distanceUnit);
            params.put("interested_men", interested_men+"");
            params.put("interested_wmen", interested_wmen+"");
            params.put("fetch", "y");
            Log.i(TAG, params+"");
            return params;
        }

    };

    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(strReq, tag_string_req);

}
}

【问题讨论】:

  • 如果你有幸使用 3rd 方库,毕加索会为你省去很多麻烦。
  • 除非您通过练习来了解非常复杂的问题以及线程和内存管理,否则一般建议是:使用库,尝试重新发明车轮。搜索 Picasso 或 Glide。

标签: android gridview android-asynctask


【解决方案1】:

如何使用 AsyncTask 加载 GridView 图像?

HomeFragment 中将图像下载为位图。在 GridView 项的布局中使用 Volley 中的 NetworkImageView 在 GridView 中加载图像。

不是存储Bitmap,而是将图像url存储在ImageItem中。

查看以下教程以获得更多帮助:

Using NetworkImageView

【讨论】:

    【解决方案2】:

    AsynTask 类

    public class GridDataAsyncTask extends AsyncTask<GridDataAsyncTask.GridCallback, Void, GridAdapter> {
    
    public interface GridCallback {
        void onAdapterReady(GridAdapter adapter);
    }
    
    private GridCallback mCallBack;
    
    @Override
    protected GridAdapter doInBackground(GridCallback... callbacks) {
        mCallBack = callbacks[0];
    
    
        // TODO get data and create grid adapter
    
        return adapter;
    }
    
    @Override
    protected void onPostExecute(GridAdapter gridAdapter) {
        super.onPostExecute(gridAdapter);
        mCallBack.onAdapterReady(gridAdapter);
    }
    }
    

    活动

    public class GridActivity extends AppCompatActivity implements GridDataAsyncTask.GridCallback {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        new GridDataAsyncTask().execute(this);
    }
    
    @Override
    public void onAdapterReady(GridAdapter adapter) {
        // TODO set adapte to GridView
    }
    }
    

    【讨论】:

      【解决方案3】:

      你能做的最好的就是使用http://developer.android.com/reference/java/util/concurrent/ThreadPoolExecutor.html 并制作一个 lru 缓存并将图像放在 lru 缓存中。 示例在 android 教程中给出 http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

      【讨论】:

        【解决方案4】:

        正如fractalwrenchBudius 所建议的那样,Picasso 是一个非常好的和非常简单的解决方案。我所要做的就是将照片 url 而不是整个位图传递给我的 GridView 适配器,并使用Picasso.with(context).load(item.getImage()).into(holder.image); 为图像视图创建位图。这很容易实现,并为我提供了我所需要的。谢谢

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-07-20
          • 1970-01-01
          • 2018-12-18
          • 1970-01-01
          • 2011-03-06
          • 1970-01-01
          • 2013-09-11
          相关资源
          最近更新 更多