Android加载用户头像的功能实现

加载用户头像的过程是,首先从本地查看是否存储了用户的头像,如果有,则从本地读取后加载到ImageView中,如果没有,则去服务器下载头像保存到本地,并加载。

public void initData() {
        super.initData();
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(MyApplication.getContext());
        final String u_id = pref.getString("u_id", "");
        // 联网请求个人中心的数据
        getDataFromServer(u_id);
    }

在Fragment的onCreateView()中调用initData()方法,该方法使用用户的id去联网请求个人中心的数据。

private void getDataFromServer(String u_id) {
        String address = Constant.PERSONAL_CENTER_URL;
        HttpUtil.sendPostRequest(address, u_id, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (null == response.body()) {
                    return;
                }

                String responseText = URLDecoder.decode(response.body().string(), "utf-8");
                // 解析数据
                processData(responseText);
            }
        });
    }

在 getDataFromServer()方法中调用了自己写的HttpUtil工具类中的方法去请求服务器数据。这个HttpUtil的方法如下:

public static void sendPostRequest(String address, String json, okhttp3.Callback callback) {
        OkHttpClient client = new OkHttpClient();
        RequestBody requestBody = RequestBody.create(JSON, json);
        Request request = new Request.Builder().url(address).post(requestBody).build();
        client.newCall(request).enqueue(callback);
    }

下面进入解析数据的部分,取出客户端返回的数据,用Gson转换为PersonMsg对象后取出User,用这个User中的数据来更新界面。从User中取出用户id,利用id去sd卡中获取到压缩后的Bitmap位图(这里是个大坑,不压缩很容易造成内存溢出OOM的错误,填坑请看我另一篇博文:解决使用Bitmap造成OOM内存溢出的问题)。如果取出的Bitmap不为空,则表示从本地加载到了用户头像,否则就从服务器请求头像数据。

    private void processData(String response) {
        final PersonMsg personMsg = Utility.handlePersonMsgResponse(response);
        if (null == personMsg) {
            return;
        }

        final User user = personMsg.getUser();

        // 更新界面
        if (getActivity() == null) {
            return;
        }

        final Bitmap bitmap = ImageUtils.getPhotoFromStorage(user.getU_id());
        if (bitmap != null) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.i("加载用户头像", "本地加载头像");
                    Glide.with(getActivity()).load(bitmap).into(mIvPhoto);
                }
            });
        } else {
            // 从服务器请求头像数据
            asyncGet(Constant.BASE_PHOTO_URL + user.getU_photo());
        }

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mTvNick.setText(user.getU_nick());
                mTvGain.setText(String.valueOf(user.getU_gain()));
                boolean male = user.getU_sex() == 1;
                if (male) {
                    Glide.with(getActivity()).load(R.drawable.ic_male).into(mIvSex);
                } else {
                    Glide.with(getActivity()).load(R.drawable.ic_female).into(mIvSex);
                }
            }
        });

        // 保存用户数据到本地数据库
        saveToDatabase(personMsg);
    }

附上用到的ImageUtils.getPhotoFromStorage()的代码部分,这部分代码就是从sd卡中取出图片并压缩的过程:

	public static Bitmap getPhotoFromStorage(String u_id) {
        String photoPath = android.os.Environment.getExternalStorageDirectory() + "/photo/" + u_id + ".jpg";
        return getBitmapFromPath(photoPath, 80, 80);
    }
    // 从路径获取Bitmap
    public static Bitmap getBitmapFromPath(String imgPath, int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imgPath, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        //避免出现内存溢出的情况,进行相应的属性设置。
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        options.inDither = true;

        return BitmapFactory.decodeFile(imgPath, options);
    }
    
	public static int calculateInSampleSize( //参2和3为ImageView期待的图片大小
                                             BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // 图片的实际大小
        final int height = options.outHeight;
        final int width = options.outWidth;
        //默认值
        int inSampleSize = 1;
        //动态计算inSampleSize的值
        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height/2;
            final int halfWidth = width/2;
            while( (halfHeight/inSampleSize) >= reqHeight && (halfWidth/inSampleSize) >= reqWidth){
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

从服务器获取图片的代码如下:

	private void asyncGet(String imgUrl) {
        OkHttpClient client = new OkHttpClient();
        final Request request = new Request.Builder().get()
                .url(imgUrl)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    if (response.body() != null) {
                        byte[] bytes = response.body().bytes();
                        final Bitmap bitmap = ImageUtils.getBitmapFromByte(bytes, 70, 70);
                        ImageUtils.savePhotoToStorage(bitmap, pref.getString("u_id", ""));
                        if (getActivity() != null) {
                            getActivity().runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Glide.with(getActivity()).load(bitmap).into(mIvPhoto);
                                }
                            });
                            Log.i("加载用户头像", "从服务器加载头像");
                        }
                    }
                }
            }
        });
    }

服务器返回的是图片的字节数组,我将其转换为压缩后的Bitmap,并将其存储到sd卡,下次读取时就可直接从sd卡中获取。

	// 保存图片到sd卡
    public static void savePhotoToStorage(Bitmap photoBitmap, String u_id) {
        //更改的名字
        String photoName = u_id + ".jpg";
        String photoPath = android.os.Environment.getExternalStorageDirectory() +
                "/photo";

        File fileDir = new File(photoPath);
        if(!fileDir.exists()){
            fileDir.mkdirs();
        }
        FileOutputStream fos = null;
        File photoFile = null;
        try{
            //重命名并保存
            photoFile = new File(photoPath, photoName);
            photoFile.createNewFile();

            fos = new FileOutputStream(photoFile);
            photoBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
	public static Bitmap getBitmapFromByte(byte[] imgByte, int reqWidth, int reqHeight) {
        InputStream input = null;
        Bitmap bitmap = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);;
        input = new ByteArrayInputStream(imgByte);
        SoftReference softRef = new SoftReference(BitmapFactory.decodeStream(
                input, null, options));
        bitmap = (Bitmap) softRef.get();
        if (imgByte != null) {
            imgByte = null;
        }

        try {
            if (input != null) {
                input.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

以上整个代码中融入了我自己项目处理的一些逻辑,实际使用中还要根据自己项目的需要来适当更改。

猜你喜欢

转载自blog.csdn.net/qq_40121502/article/details/83628879