### Example Android XML Layout Using BlurredView Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/BlurDemo/README.md Demonstrates how to integrate the custom `BlurredView` into an Android layout, setting its width, height, initial image source (`app:src`), and enabling/disabling blurring (`app:disableBlurred`) directly in the XML. ```XML ``` -------------------------------- ### Example of a Complex Nested JSON Structure Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/GsonArrayDemo/README.md A sample JSON object demonstrating a nested structure with 'group', 'user', and 'info' objects, used as the target for parsing examples. ```JSON { "group": { "user": { "name": "张三", "age": "10", "phone": "11111", "email": "11111@11.com" }, "info": { "address": "北京", "work": "Android Dev", "pay": "10K", "motto": "先定一个小目标,比如我先赚一个亿" } } } ``` -------------------------------- ### RxJava Observable.just() with Null and Observer Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Illustrates the behavior of `Observable.just()` when emitting `null` values and how to subscribe to an `Observable` using an `Observer`. The example includes `onNext`, `onCompleted`, and `onError` callbacks, specifically handling `null` in `onNext`. ```Java //创建Observable Observable.just("Hello", "World", null) .subscribe(new Observer() { @Override public void onNext(String s) { if (s == null) { Log.i("onNext ---> ", "null"); }else { Log.i("onNext ---> ", s); } } @Override public void onCompleted() { Log.i("onCompleted ---> ", "完成"); } @Override public void onError(Throwable e) { Log.i("onError ---> ", "出错 --->" + e.toString()); } }); ``` -------------------------------- ### Example Complex JSON Data Structure Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/GsonArrayDemo/README.md This JSON structure illustrates a typical complex data format, featuring a root object with 'code', 'msg', and a 'muser' array containing multiple user objects. This serves as the target structure for all parsing examples. ```JSON { "code": 200, "msg": "OK", "muser": [ { "name": "zhangsan", "age": "10", "phone": "11111", "email": "11111@11.com" }, { "name": "lisi", "age": "20", "phone": "22222", "email": "22222@22.com" }, ... ] } ``` -------------------------------- ### Example Android Java Activity Setting BlurredView Level Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/BlurDemo/README.md Shows how to programmatically interact with the `BlurredView` from an Android Activity. It retrieves the `BlurredView` instance by ID and sets its blur level using the `setBlurredLevel` method, demonstrating dynamic control over the blur effect. ```Java private void initView() { customBView = (BlurredView) findViewById(R.id.bv_custom_blur); //设置模糊度 customBView.setBlurredLevel(100); } ``` -------------------------------- ### Basic Add and Retrieve Operations for Android LruCache Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md This snippet illustrates the fundamental `get` and `put` operations for interacting with an `LruCache` instance. These methods allow for adding new key-value pairs to the cache and retrieving cached objects, similar to a standard `Map` interface. ```Java //添加到缓存 mCache.get(key); //从缓存中获取 mCache.put(key,value); ``` -------------------------------- ### Get Usable Disk Space (Java) Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之DiskLruCache详谈.md Calculates the available space on a given file path. It uses `path.getUsableSpace()` for Android API Level 9 (Gingerbread) and above, falling back to `StatFs` for older versions. ```Java private long getUsableSpace(File path) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { return path.getUsableSpace(); } final StatFs stats = new StatFs(path.getPath()); return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks(); } ``` -------------------------------- ### Retrieving Images from DiskLruCache in Android Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之DiskLruCache详谈.md This snippet illustrates how to retrieve an image from DiskLruCache using its key. It involves obtaining a Snapshot object from the cache, then getting an InputStream from the Snapshot to read the cached image data. Similar to adding, this operation should not be performed on the UI thread. ```Java /** * 从缓存中取出Bitmap * * @param url 图片的URL * @return 返回Bitmap对象 * @throws IOException */ private Bitmap getBitmapFromDiskCache(String url) throws IOException { //如果当前线程是主线程 则异常 if (Looper.myLooper() == Looper.getMainLooper()) { Log.w(TAG, "load bitmap from UI Thread, it's not recommended!"); } //如果缓存中为空 直接返回为空 if (mDiskCache == null) { return null; } //通过key值在缓存中找到对应的Bitmap Bitmap bitmap = null; String key = hashKeyFormUrl(url); //通过key得到Snapshot对象 DiskLruCache.Snapshot snapShot = mDiskCache.get(key); if (snapShot != null) { //得到文件输入流 FileInputStream fileInputStream = (FileInputStream) snapShot.getInputStream(DISK_CACHE_INDEX); FileDescriptor fileDescriptor = fileInputStream.getFD(); bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor); } return bitmap; } ``` -------------------------------- ### Get Disk Cache Directory (Java) Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之DiskLruCache详谈.md Determines the appropriate directory for disk caching based on external storage availability. It returns a `File` object representing the cache directory for the given file path. ```Java public File getDiskCacheDir(Context context, String filePath) { boolean externalStorageAvailable = Environment .getExternalStorageState().equals(Environment.MEDIA_MOUNTED); final String cachePath; if (externalStorageAvailable) { cachePath = context.getExternalCacheDir().getPath(); } else { cachePath = context.getCacheDir().getPath(); } return new File(cachePath + File.separator + filePath); } ``` -------------------------------- ### Parsing JSON Array Without a Root Header using GSON Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/GsonArrayDemo/README.md This section explains how to parse a simple JSON array that lacks a root key or header. While GSON can directly parse this into a List, the example demonstrates a more explicit method to introduce `JsonParser` and `JsonElement`. The parsing steps involve converting the JSON string to a `JsonArray` using `JsonParser`, then iterating through each `JsonElement` and converting it to a `UserBean` object using GSON. `JsonParser` is used to convert JSON strings to `JsonObject` or `JsonArray`, and `JsonElement` represents any JSON element (object, array, primitive). ```JSON [ { "name": "zhangsan", "age": "10", "phone": "11111", "email": "11111@11.com" }, { "name": "lisi", "age": "20", "phone": "22222", "email": "22222@22.com" }, ... ] ``` ```Java public class UserBean { //变量名跟JSON数据的字段名需要一致 private String name ; private String age; private String phone; private String email; ... } ``` ```Java /** * 解析没有数据头的纯数组 */ private void parseNoHeaderJArray() { //拿到本地JSON 并转成String String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_1); //Json的解析类对象 JsonParser parser = new JsonParser(); //将JSON的String 转成一个JsonArray对象 JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray(); Gson gson = new Gson(); ArrayList userBeanList = new ArrayList<>(); //加强for循环遍历JsonArray for (JsonElement user : jsonArray) { //使用GSON,直接转成Bean对象 UserBean userBean = gson.fromJson(user, UserBean.class); userBeanList.add(userBean); } mainLView.setAdapter(new UserAdapter(this, userBeanList)); } ``` -------------------------------- ### RxJava Observable.create() Source Code Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Examines the internal implementation of `Observable.create()`, showing how it constructs an `Observable` instance and stores the `OnSubscribe` function. It also details the role of `hook.onCreate`. ```Java public static Observable create(OnSubscribe f) { return new Observable(hook.onCreate(f)); } ``` -------------------------------- ### Creating an Observer in RxJava Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Demonstrates how to create an Observer instance by implementing its interface. It shows the onNext, onCompleted, and onError callback methods, which are fundamental to handling events in RxJava. ```Java //创建Observer Observer observer = new Observer() { @Override public void onNext(String s) { Log.i("onNext ---> ", "Item: " + s); } @Override public void onCompleted() { Log.i("onCompleted ---> ", "完成"); } @Override public void onError(Throwable e) { Log.i("onError ---> ", e.toString()); } }; ``` -------------------------------- ### RxJava Observable Constructor Source Code Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Provides the source code for the `Observable` class constructor, illustrating how it initializes the `onSubscribe` field with the provided `OnSubscribe` function. ```Java protected Observable(OnSubscribe f) { this.onSubscribe = f; } ``` -------------------------------- ### RxJavaObservableExecutionHook.onCreate() Source Code Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Shows the source code for the `onCreate` method within `RxJavaObservableExecutionHook`, clarifying its minimal role as a debugging hook that simply returns the input `OnSubscribe` function. ```Java public OnSubscribe onCreate(OnSubscribe f) { return f; } ``` -------------------------------- ### Creating an Observable in RxJava Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Illustrates how to create an Observable using the create() method. It shows how to emit data using onNext() and signal completion with onCompleted() within the call method of Observable.OnSubscribe. ```Java //创建Observable Observable observable = Observable.create(new Observable.OnSubscribe() { @Override public void call(Subscriber subscriber) { subscriber.onNext("Hello"); subscriber.onNext("World"); subscriber.onCompleted(); } }); ``` -------------------------------- ### Android: Gradle Configuration for RenderScript Support Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/BlurDemo/README.md To enable RenderScript functionality in an Android project, specific configurations must be added to the module's `build.gradle` file within the `defaultConfig` block. This snippet sets the `renderscriptTargetApi` and enables `renderscriptSupportModeEnabled` for compatibility across different Android versions. A note on `minSdkVersion` is also included. ```Gradle defaultConfig { renderscriptTargetApi 19 renderscriptSupportModeEnabled true } ``` -------------------------------- ### RxJava Observable.create() and Subscription Flow Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Demonstrates the `Observable.create()` method, which allows custom `Observable` creation logic. It highlights the execution order between the `OnSubscribe.call()` method and the `Observer` callbacks (`onNext`, `onCompleted`) during subscription. ```Java //创建Observable Observable.create(new Observable.OnSubscribe() { @Override public void call(Subscriber subscriber) { subscriber.onNext("Hello"); subscriber.onNext("World"); subscriber.onCompleted(); Log.i("执行顺序 ---> ", " call "); } }).subscribe(new Observer() { @Override public void onNext(String s) { Log.i("onNext ---> ", s); Log.i("执行顺序 ---> ", " subscribe onNext"); } @Override public void onCompleted() { Log.i("onCompleted ---> ", "完成"); Log.i("执行顺序 ---> ", " subscribe onCompleted"); } @Override public void onError(Throwable e) { Log.i("onError ---> ", "出错 --->" + e.toString()); } }); ``` -------------------------------- ### RxJava Observable.just() Basic Usage Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Demonstrates the simplest use of `Observable.just()` to emit a sequence of predefined items. It shows how `just()` can emit multiple string values. ```Java Observable.just("Hello","world"); //其实就相当于依次调用: //subscriber.onNext("Hello"); //subscriber.onNext("World"); ``` -------------------------------- ### RxJava ActionX Interfaces API Documentation Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Documentation for RxJava's `ActionX` interfaces, which are used to define actions (methods without return values) for incomplete callbacks. `Action1` handles single-argument methods like `onNext` and `onError`, while `Action0` handles zero-argument methods like `onCompleted`. ```APIDOC ActionX Interfaces: Action1: - Extends: Action - Method: void call(T t) - Description: A one-argument action. Used for packaging onNext(obj) and onError(error) into subscribe() for incomplete callbacks. Action0: - Extends: Action - Method: void call() - Description: A zero-argument action. Used for packaging onCompleted() into subscribe() for incomplete callbacks. General: - RxJava provides multiple ActionX forms (e.g., Action2, Action3) for wrapping different numbers of arguments without return values. ``` -------------------------------- ### Android: Applying Gaussian Blur to an ImageView Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/BlurDemo/README.md This code snippet demonstrates how to integrate the `BlurBitmapUtil` into an Android `Activity` or `Fragment` to apply a Gaussian blur effect to an `ImageView`. It shows the steps of obtaining the source Bitmap from resources, calling the `BlurBitmapUtil.blurBitmap` method with a specified blur radius, and then setting the resulting blurred Bitmap to the `ImageView`. ```Java /** * 初始化View */ @SuppressWarnings("deprecation") private void initView() { basicImage = (ImageView) findViewById(R.id.iv_basic_pic); //拿到初始图 Bitmap initBitmap = BitmapUtil.drawableToBitmap(getResources().getDrawable(R.raw.pic)); //处理得到模糊效果的图 Bitmap blurBitmap = BlurBitmapUtil.blurBitmap(this, initBitmap, 20f); basicImage.setImageBitmap(blurBitmap); } ``` -------------------------------- ### Complete LruCacheUtil for Asynchronous Image Caching Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md This is the full implementation of the `LruCacheUtil` class, designed for asynchronous image loading and caching using `LruCache`. The constructor initializes the cache with a size based on available memory and sets up a `HashSet` to track active `NewsAsyncTask` instances. It includes the `sizeOf` override for `LruCache` to correctly measure Bitmap sizes and a `showImageByAsyncTask` method for displaying images. ```Java /** * 异步加载图片的工具类 */ public class LruCacheUtil { //LRU缓存 private LruCache mCache; private ListView mListView; private Set mTaskSet; public LruCacheUtil(ListView listView) { this.mListView = listView; mTaskSet = new HashSet<>(); //返回Java虚拟机将尝试使用的最大内存 int maxMemory = (int) Runtime.getRuntime().maxMemory(); //指定缓存大小 int cacheSize = maxMemory / 4; mCache = new LruCache(cacheSize) { @Override protected int sizeOf(String key, Bitmap value) { //Bitmap的实际大小 注意单位与maxMemory一致 return value.getByteCount(); //也可以这样返回 结果是一样的 //return value.getRowBytes()*value.getHeight(); } }; } /** * 通过异步任务的方式加载数据 * * @param iv 图片的控件 * @param url 图片的URL */ public void showImageByAsyncTask(ImageView iv, final String url) { //从缓存中取出图片 Bitmap bitmap = getBitmapFromCache(url); //如果缓存中没有,则需要从网络中下载 if (bitmap == null) { bitmap = getBitmapFromURL(url); iv.setImageBitmap(bitmap); ``` -------------------------------- ### RxJava FuncX Interfaces API Documentation Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Documentation for RxJava's `FuncX` interfaces, which are used to define functions (methods with return values). `Func1` handles single-argument methods with a return type. Unlike `ActionX`, `FuncX` interfaces always return a value. ```APIDOC FuncX Interfaces: Func1: - Extends: Function - Method: R call(T t) - Description: Represents a function with one argument (T) and a result type (R). Used for packaging methods that have a return value. General: - FuncX interfaces (e.g., Func2, Func3) exist for different numbers of arguments. - Key difference from ActionX: FuncX wraps methods with return values, while ActionX wraps methods without return values. ``` -------------------------------- ### Implement Android ListView ViewHolder Pattern for Performance Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md This Java code demonstrates the `ViewHolder` pattern within an Android `ListView` adapter's `getView` method. It reuses `convertView` to optimize scrolling performance and includes a static `ViewHolder` inner class to hold view references, preventing repeated `findViewById` calls. It also shows initial image loading and binding image URLs to `ImageView` tags. ```Java ViewHolder viewHolder; if (convertView == null) { convertView = View.inflate(context, R.layout.item_news, null); } // 得到一个ViewHolder viewHolder = ViewHolder.getViewHolder(convertView); //先加载默认图片 防止有的没有图 viewHolder.iconImage.setImageResource(R.mipmap.ic_launcher); String iconUrl = list.get(position).newsIconUrl; //当前位置的ImageView与图片的URL绑定 viewHolder.iconImage.setTag(iconUrl); //再加载联网图 //第一种方式 通过子线程设置 new ThreadUtil().showImageByThread(viewHolder.iconImage, iconUrl); viewHolder.titleText.setText(list.get(position).newsTitle); viewHolder.contentText.setText(list.get(position).newsContent); return convertView; } static class ViewHolder { ImageView iconImage; TextView titleText; TextView contentText; // 构造函数中就初始化View public ViewHolder(View convertView) { iconImage = (ImageView) convertView.findViewById(R.id.iv_icon); titleText = (TextView) convertView.findViewById(R.id.tv_title); contentText = (TextView) convertView.findViewById(R.id.tv_content); } // 得到一个ViewHolder public static ViewHolder getViewHolder(View convertView) { ViewHolder viewHolder = (ViewHolder) convertView.getTag(); if (viewHolder == null) { viewHolder = new ViewHolder(convertView); convertView.setTag(viewHolder); } return viewHolder; } } ``` -------------------------------- ### Calling DiskLruCache Utility for Async Image Loading Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之DiskLruCache详谈.md This snippet demonstrates how to invoke a utility method, `showImageByAsyncTask`, to load and display an image using `DiskLruCache` for disk storage. It's wrapped in a try-catch block to handle potential `IOException` during the caching process. ```Java //第三种方式 通过异步任务方式设置 且利用DiskLruCache存储到磁盘缓存中 try { mDiskCacheUtil.showImageByAsyncTask(viewHolder.iconImage, iconUrl); } catch (IOException e) { e.printStackTrace(); } ``` -------------------------------- ### Core Java Class: BlurredView Implementation Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/BlurDemo/README.md Partial implementation of the `BlurredView` class, extending `RelativeLayout`. It includes global constants, `ImageView` references for original and blurred images, `Bitmap` objects, and a boolean flag to disable blurring. Key methods like `setBlurredImg`, `setImageView`, and `setBlurredLevel` are shown, demonstrating how images are processed and blur levels are controlled via alpha transparency. ```Java /** * @author Qiushui * @description 自定义模糊View类 * @revision Xiarui 16.09.05 */ public class BlurredView extends RelativeLayout { /*========== 全局相关 ==========*/ private Context mContext;//上下文对象 private static final int ALPHA_MAX_VALUE = 255;//透明最大值 private static final float BLUR_RADIUS = 25f;//最大模糊度(在0.0到25.0之间) /*========== 图片相关 ==========*/ private ImageView mOriginImg;//原图ImageView private ImageView mBlurredImg;//模糊后的ImageView private Bitmap mBlurredBitmap;//模糊后的Bitmap private Bitmap mOriginBitmap;//原图Bitmap /*========== 属性相关 ==========*/ private boolean isDisableBlurred;//是否禁用模糊效果 ... /** * 以代码的方式添加待模糊的图片 * * @param blurredBitmap 待模糊的图片 */ public void setBlurredImg(Bitmap blurredBitmap) { if (null != blurredBitmap) { mOriginBitmap = blurredBitmap; mBlurredBitmap = BlurBitmapUtil.blurBitmap(mContext, blurredBitmap, BLUR_RADIUS); setImageView(); } } ... /** * 填充ImageView */ private void setImageView() { mBlurredImg.setImageBitmap(mBlurredBitmap); mOriginImg.setImageBitmap(mOriginBitmap); } /** * 设置模糊程度 * * @param level 模糊程度, 数值在 0~100 之间. */ @SuppressWarnings("deprecation") public void setBlurredLevel(int level) { //超过模糊级别范围 直接抛异常 if (level < 0 || level > 100) { throw new IllegalStateException("No validate level, the value must be 0~100"); } //禁用模糊直接返回 if (isDisableBlurred) { return; } //设置透明度 mOriginImg.setAlpha((int) (ALPHA_MAX_VALUE - level * 2.55)); } ... } ``` -------------------------------- ### Android: Gaussian Blur Utility Class with RenderScript Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/BlurDemo/README.md This utility class provides a static method `blurBitmap` to apply a Gaussian blur effect to a given Bitmap using Android's RenderScript framework. It scales down the image for performance, creates RenderScript context and blur script, allocates memory, sets the blur radius, and processes the image efficiently. The `BITMAP_SCALE` constant controls the downscaling factor. ```Java /** * @author Qiushui * @description 模糊图片工具类 * @revision Xiarui 16.09.05 */ public class BlurBitmapUtil { //图片缩放比例 private static final float BITMAP_SCALE = 0.4f; /** * 模糊图片的具体方法 * * @param context 上下文对象 * @param image 需要模糊的图片 * @return 模糊处理后的图片 */ public static Bitmap blurBitmap(Context context, Bitmap image,float blurRadius) { // 计算图片缩小后的长宽 int width = Math.round(image.getWidth() * BITMAP_SCALE); int height = Math.round(image.getHeight() * BITMAP_SCALE); // 将缩小后的图片做为预渲染的图片 Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false); // 创建一张渲染后的输出图片 Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap); // 创建RenderScript内核对象 RenderScript rs = RenderScript.create(context); // 创建一个模糊效果的RenderScript的工具对象 ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); // 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间 // 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去 Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap); Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap); // 设置渲染的模糊程度, 25f是最大模糊度 blurScript.setRadius(blurRadius); // 设置blurScript对象的输入内存 blurScript.setInput(tmpIn); // 将输出数据保存到输出内存中 blurScript.forEach(tmpOut); // 将数据填充到Allocation中 tmpOut.copyTo(outputBitmap); return outputBitmap; } } ``` -------------------------------- ### RxJava Observable.from() Basic Usage Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md Shows how `Observable.from()` can convert an array into an `Observable` that emits each item of the array sequentially. This operator is useful for processing collections. ```Java String[] str = new String[]{"Hello", "World"}; //创建Observable Observable.from(str); ``` -------------------------------- ### Implementing Deferred Image Loading in NewsAdapter Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md The `NewsAdapter` class is extended to implement `AbsListView.OnScrollListener`. It manages the visible item range during scrolling and triggers image loading only when the ListView is idle (`SCROLL_STATE_IDLE`). During active scrolling, any pending image loading tasks are cancelled to prevent unnecessary work. The adapter also initializes an `LruCacheUtil` instance and registers itself as the scroll listener. ```Java /** * 新闻列表适配器 */ public class NewsAdapter extends BaseAdapter implements AbsListView.OnScrollListener { private Context context; private List list; private LruCacheUtil lruCacheUtil; private int mStart, mEnd;//滑动的起始位置 public static String[] urls; //用来保存当前获取到的所有图片的Url地址 //是否是第一次进入 private boolean mFirstIn; public NewsAdapter(Context context, List list, ListView lv) { this.context = context; this.list = list; lruCacheUtil = new LruCacheUtil(lv); //存入url地址 urls = new String[list.size()]; for (int i = 0; i < list.size(); i++) { urls[i] = list.get(i).newsIconUrl; } mFirstIn = true; //注册监听事件 lv.setOnScrollListener(this); } ... /** * 滑动状态改变的时候才会去调用此方法 * * @param view 滚动的View * @param scrollState 滚动的状态 */ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == SCROLL_STATE_IDLE) { //加载可见项 lruCacheUtil.loadImages(mStart, mEnd); } else { //停止加载任务 lruCacheUtil.cancelAllTask(); } } /** * 滑动过程中 一直会调用此方法 * * @param view 滚动的View * @param firstVisibleItem 第一个可见的item * @param visibleItemCount 可见的item的长度 * @param totalItemCount 总共item的个数 */ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mStart = firstVisibleItem; mEnd = firstVisibleItem + visibleItemCount; //如果是第一次进入 且可见item大于0 预加载 if (mFirstIn && visibleItemCount > 0) { try { lruCacheUtil.loadImages(mStart, mEnd); } catch (IOException e) { e.printStackTrace(); } mFirstIn = false; } } } ``` -------------------------------- ### Initialize Android LruCache for Bitmap Memory Caching Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md This Java code demonstrates how to initialize an `LruCache` instance for in-memory caching of `Bitmap` objects. It calculates the cache size as a fraction of the application's maximum available memory and overrides the `sizeOf` method to accurately measure the byte count of each `Bitmap`. ```Java //返回Java虚拟机将尝试使用的最大内存 int maxMemory = (int) Runtime.getRuntime().maxMemory(); //指定缓存大小 int cacheSize = maxMemory / 4; mCache = new LruCache(cacheSize) { @Override protected int sizeOf(String key, Bitmap value) { //Bitmap的实际大小 注意单位与maxMemory一致 return value.getByteCount(); //也可以这样返回 结果是一样的 //return value.getRowBytes()*value.getHeight(); } }; ``` -------------------------------- ### Android AsyncTask for Image Loading and Disk Caching Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之DiskLruCache详谈.md This `AsyncTask` implementation handles background image loading from a URL and caching the bitmap to disk. The `doInBackground` method fetches the image and adds it to a disk cache, while `onPostExecute` updates an `ImageView` on the UI thread once the image is loaded and removes the task from a set. ```Java protected Bitmap doInBackground(String... params) { Bitmap bitmap = getBitmapFromURL(params[0]); //保存到缓存中 if (bitmap != null) { try { //写入缓存 addBitmapToDiskCache(params[0]); } catch (IOException e) { e.printStackTrace(); } } return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); ImageView imageView = (ImageView) mListView.findViewWithTag(url); if (imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap); } mTaskSet.remove(this); } ``` -------------------------------- ### Load Images with Caching and Async Task in Android Java Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md This method iterates through a specified range of image URLs to load them. It first attempts to retrieve the image from the `LruCache`. If the image is not found in the cache, a `NewsAsyncTask` is initiated to download and cache it asynchronously. If found, the image is directly set to the corresponding `ImageView`. ```Java public void loadImages(int start, int end) { for (int i = start; i < end; i++) { String url = NewsAdapter.urls[i]; //从缓存中取出图片 Bitmap bitmap = getBitmapFromCache(url); //如果缓存中没有,则需要从网络中下载 if (bitmap == null) { NewsAsyncTask task = new NewsAsyncTask(url); task.execute(url); mTaskSet.add(task); } else { //如果缓存中有 直接设置 ImageView imageView = (ImageView) mListView.findViewWithTag(url); imageView.setImageBitmap(bitmap); } } } ``` -------------------------------- ### Concise Gson Parsing of Complex JSON to User List (One-liner) Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/GsonArrayDemo/README.md This snippet shows a highly condensed version of the conventional parsing method, achieving the same result in a single line of code. While compact, this approach can reduce readability and maintainability, and is generally not recommended for complex operations. ```Java mainLView.setAdapter(new ResultAdapter(this,new Gson().fromJson(JsonToStringUtil.getStringByJson(this,R.raw.juser_3),ResultBean.class).getMuser())); ``` -------------------------------- ### Asynchronous Image Loading and Caching Task in Android Java Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md This inner `AsyncTask` class handles the background downloading and caching of images. The `doInBackground` method fetches the bitmap from the URL and adds it to the `LruCache`. The `onPostExecute` method updates the `ImageView` on the UI thread with the downloaded bitmap and removes the task from the active task set. ```Java private class NewsAsyncTask extends AsyncTask { private String url; public NewsAsyncTask(String url) { this.url = url; } @Override protected Bitmap doInBackground(String... params) { Bitmap bitmap = getBitmapFromURL(params[0]); //保存到缓存中 if (bitmap != null) { addBitmapToCache(params[0], bitmap); } return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); //只有当前的ImageView所对应的UR的图片是一致的,才会设置图片 ImageView imageView = (ImageView) mListView.findViewWithTag(url); if (imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap); } //移除所有Task mTaskSet.remove(this); } } ``` -------------------------------- ### Implementing Dynamic Blur with Touch Events in Android Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/BlurDemo/README.md This code snippet demonstrates how to achieve a dynamic blur effect by responding to user touch events. It initializes a `BlurredView` with a default blur level and then, within the `onTouchEvent` method, calculates the new blur level based on the vertical finger movement. The blur level is adjusted proportionally to the finger's displacement relative to the screen height, ensuring the blur remains within a 0-100 range. The `setBlurredLevel` method is called to update the view's blur intensity. ```Java /** * 初始化View */ private void initView() { customBView = (BlurredView) findViewById(R.id.bv_dynamic_blur); //设置初始模糊度 initLevel = 100; customBView.setBlurredLevel(initLevel); } /** * 触摸事件 */ @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downY = ev.getY(); break; case MotionEvent.ACTION_MOVE: float moveY = ev.getY(); //手指滑动距离 float offsetY = moveY - downY; //屏幕高度 十倍是为了看出展示效果 int screenY = getWindowManager().getDefaultDisplay().getHeight() * 10; //手指滑动距离占屏幕的百分比 movePercent = offsetY / screenY; currentLevel = initLevel + (int) (movePercent * 100); if (currentLevel < 0) { currentLevel = 0; } if (currentLevel > 100) { currentLevel = 100; } //设置模糊度 customBView.setBlurredLevel(currentLevel); //更改初始模糊等级 initLevel = currentLevel; break; case MotionEvent.ACTION_UP: break; } return super.onTouchEvent(ev); } ``` -------------------------------- ### Transforming Data with RxJava Map Operator Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/FirstRxJavaDemo/README.md This snippet demonstrates how to use the RxJava `Map` operator to transform a `String` URL into a `Bitmap` object. It uses `Observable.just()` to emit the URL, `map()` with `Func1` to perform the transformation on an IO thread, and `subscribe()` with `Action1` to update the UI on the main thread with the resulting Bitmap. ```Java //先传递String类型的Url Observable.just(url) .map(new Func1() { @Override public Bitmap call(String s) { //通过Map转换成Bitmap类型发送出去 return GetBitmapForURL.getBitmap(s); } }) .subscribeOn(Schedulers.io()) // 指定subscribe()发生在IO线程 .observeOn(AndroidSchedulers.mainThread()) // 指定Subscriber的回调发生在UI线程 //可以看到,这里接受的类型是Bitmap,而不是String .subscribe(new Action1() { @Override public void call(Bitmap bitmap) { mainImageView.setImageBitmap(bitmap); mainProgressBar.setVisibility(View.GONE); } }); ``` -------------------------------- ### Managing Image Loading Tasks with LruCacheUtil Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md These methods from `LruCacheUtil` handle the core logic for loading and cancelling image tasks. `loadImages` iterates through visible items, checking the LRU cache first. If an image is not cached, a `NewsAsyncTask` is initiated and added to a `mTaskSet`. `cancelAllTask` iterates through this set to cancel any ongoing `NewsAsyncTask` instances, ensuring tasks are stopped during active scrolling. ```Java /** * 加载从start到end的所有的Image * * @param start * @param end */ public void loadImages(int start, int end) { for (int i = start; i < end; i++) { String url = NewsAdapter.urls[i]; //从缓存中取出图片 Bitmap bitmap = getBitmapFromCache(url); //如果缓存中没有,则需要从网络中下载 if (bitmap == null) { NewsAsyncTask task = new NewsAsyncTask(url); task.execute(url); mTaskSet.add(task); } else { //如果缓存中有 直接设置 ImageView imageView = (ImageView) mListView.findViewWithTag(url); imageView.setImageBitmap(bitmap); } } } /** * 停止所有当前正在运行的任务 */ public void cancelAllTask() { if (mTaskSet != null) { for (NewsAsyncTask task : mTaskSet) { task.cancel(false); } } } ``` -------------------------------- ### Convert URL to Bitmap in Android Java Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md This method downloads an image from a given URL and converts it into a `Bitmap` object. It uses `HttpURLConnection` for network communication and `BitmapFactory.decodeStream` for decoding the image stream, handling potential `IOException` during the process. ```Java public Bitmap getBitmapFromURL(String urlStr) { Bitmap bitmap; InputStream is = null; try { URL url = new URL(urlStr); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); is = new BufferedInputStream(connection.getInputStream()); bitmap = BitmapFactory.decodeStream(is); connection.disconnect(); return bitmap; } catch (java.io.IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } ``` -------------------------------- ### Android XML Layout for BlurredView Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/BlurDemo/README.md Defines the basic layout structure for the custom `BlurredView`, inheriting from `FrameLayout` and containing two `ImageView`s stacked on top of each other: one for the blurred image and one for the original image. ```XML ``` -------------------------------- ### Android XML Custom Attributes for BlurredView Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/BlurDemo/README.md Defines custom attributes for the `BlurredView` in `resources.xml`, allowing configuration of the image source (`src`) and whether blurring is disabled (`disableBlurred`) directly from layout files. ```XML ``` -------------------------------- ### Asynchronous Task for Image Loading (Java) Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之DiskLruCache详谈.md Defines an `AsyncTask` subclass, `NewsAsyncTask`, designed for performing background operations like image loading. It holds the URL for the image to be processed. ```Java private class NewsAsyncTask extends AsyncTask { private String url; public NewsAsyncTask(String url) { this.url = url; } @Override ``` -------------------------------- ### Generate MD5 Hash Key from URL (Java) Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之DiskLruCache详谈.md Converts a URL string into a unique cache key using MD5 hashing. If MD5 algorithm is not available, it falls back to the URL's `hashCode()`. ```Java private String hashKeyFormUrl(String url) { String cacheKey; try { final MessageDigest mDigest = MessageDigest.getInstance("MD5"); mDigest.update(url.getBytes()); cacheKey = bytesToHexString(mDigest.digest()); } catch (NoSuchAlgorithmException e) { cacheKey = String.valueOf(url.hashCode()); } return cacheKey; } ``` -------------------------------- ### Adding Images to DiskLruCache in Android Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之DiskLruCache详谈.md This snippet demonstrates how to add an image to DiskLruCache. It involves downloading the image from a URL to an OutputStream and then using DiskLruCache's Editor object to commit the data to the cache. It's crucial to check the Editor's availability and perform these operations off the main UI thread. ```Java /** * 将URL中的图片保存到输出流中 * * @param urlString 图片的URL地址 * @param outputStream 输出流 * @return 输出流 */ private boolean downloadUrlToStream(String urlString, OutputStream outputStream) { HttpURLConnection urlConnection = null; BufferedOutputStream out = null; BufferedInputStream in = null; try { final URL url = new URL(urlString); urlConnection = (HttpURLConnection) url.openConnection(); in = new BufferedInputStream(urlConnection.getInputStream(), IO_BUFFER_SIZE); out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE); int b; while ((b = in.read()) != -1) { out.write(b); } return true; } catch (final IOException e) { e.printStackTrace(); } finally { if (urlConnection != null) { urlConnection.disconnect(); } try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (final IOException e) { e.printStackTrace(); } } return false; } /** * 将Bitmap写入缓存 * * @param url * @return * @throws IOException */ private Bitmap addBitmapToDiskCache(String url) throws IOException { //如果当前线程是在主线程 则异常 if (Looper.myLooper() == Looper.getMainLooper()) { throw new RuntimeException("can not visit network from UI Thread."); } if (mDiskCache == null) { return null; } //设置key,并根据URL保存输出流的返回值决定是否提交至缓存 String key = hashKeyFormUrl(url); DiskLruCache.Editor editor = mDiskCache.edit(key); if (editor != null) { OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX); if (downloadUrlToStream(url, outputStream)) { editor.commit(); } else { editor.abort(); } mDiskCache.flush(); } return getBitmapFromDiskCache(url); } ``` -------------------------------- ### Parsing Complex JSON to Java Bean using Gson (Conventional Method) Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/GsonArrayDemo/README.md This method demonstrates the standard approach to parse an entire complex JSON string into a `ResultBean` object using Gson's `fromJson` method. It then retrieves the list of `UserBean` objects from the deserialized `ResultBean` and displays them. This approach is straightforward for full deserialization. ```Java /** * 有消息头 复杂数据 常规方式 */ private void parseComplexJArrayByCommon() { //拿到Json字符串 String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3); //GSON直接解析成对象 ResultBean resultBean = new Gson().fromJson(strByJson,ResultBean.class); //对象中拿到集合 List userBeanList = resultBean.getMuser(); //展示到UI中 mainLView.setAdapter(new ResultAdapter(this, userBeanList)); } ``` -------------------------------- ### Retrieve Bitmap from LruCache in Android Java Source: https://github.com/iamxiarui/android_5.0_viewdemo/blob/master/MoocNewsDemo/src/main/Android:跟着实战项目学缓存策略之LruCache详谈.md This method retrieves a `Bitmap` object from the `LruCache` using its URL as the key. It provides quick access to cached images, significantly reducing the need for repeated network requests and improving application responsiveness. ```Java public Bitmap getBitmapFromCache(String url) { return mCache.get(url); } ```