Android ExpandableListView可展开列表
目录
- 效果图
- 准备测试数据
- ExpandableListView适配器编写
- getGroupView()方法
- getChildView()方法
- isChildSelectable()方法
- hasStableIds()方法
- MyExpandableAdapter适配器的完整代码
- 组item的布局文件
- 子item的布局文件
- ViewHolder完整代码
- 主页面
- ExpandableListView属性设置
- 分割线
- ExpandableListView的数据刷新
- 设置默认展开全部
- 主页面完整代码
- 源码
效果图
ExpandableListView继承于ListView,先上图,看一下效果:

准备测试数据
列表分为组item和子item,它们都由文字和icon组成,在assets文件夹下创建一个json文件ExpandableMode.json用于存放测试数据,结构如下:
[{"GroupName": "水果","GroupIcon": "icon_fruit","ChildData": [{"ChildName": "香蕉","ChildIcon": "icon_banana","Number": 5},{"ChildName": "苹果","ChildIcon": "icon_apple","Number": 3},{"ChildName": "西瓜","ChildIcon": "icon_watermelon","Number": 9}]},{"GroupName": "蔬菜","GroupIcon": "icon_vegetable","ChildData": [{"ChildName": "萝卜","ChildIcon": "icon_radish","Number": 4},{"ChildName": "西红柿","ChildIcon": "icon_tomatoes","Number": 7},{"ChildName": "榴莲","ChildIcon": "icon_durian","Number": 9}]},{"GroupName": "交通工具","GroupIcon": "icon_traffic","ChildData": [{"ChildName": "汽车","ChildIcon": "icon_car","Number": 4},{"ChildName": "飞机","ChildIcon": "icon_plane","Number": 7},{"ChildName": "大炮","ChildIcon": "icon_cannon","Number": 9},{"ChildName": "火箭","ChildIcon": "icon_rocket","Number": 1}]}
]
创建一个和json文件相对应的实体类ExpandableMode
package top.zhaohaibo.expandable.mode;import java.util.List;/*** 作者: Ocean
* 时间: 2020/3/28 9:57 PM
* 邮箱: xinzhaohaibo@aliyun.com
* 描述: 可展开视图的数据模型*/
public class ExpandableMode {/*** GroupName : 水果* GroupIcon :* ChildData : [{"ChildName":"香蕉","ChildIcon":"","Number":5},{"ChildName":"苹果","ChildIcon":"","Number":3},{"ChildName":"西瓜","ChildIcon":"","Number":9}]*/private String GroupName;private String GroupIcon;private List<ChildDataBean> ChildData;public String getGroupName() {return GroupName;}public void setGroupName(String GroupName) {this.GroupName = GroupName;}public String getGroupIcon() {return GroupIcon;}public void setGroupIcon(String GroupIcon) {this.GroupIcon = GroupIcon;}public List<ChildDataBean> getChildData() {return ChildData;}public void setChildData(List<ChildDataBean> ChildData) {this.ChildData = ChildData;}public static class ChildDataBean {/*** ChildName : 香蕉* ChildIcon :* Number : 5*/private String ChildName;private String ChildIcon;private int Number;public String getChildName() {return ChildName;}public void setChildName(String ChildName) {this.ChildName = ChildName;}public String getChildIcon() {return ChildIcon;}public void setChildIcon(String ChildIcon) {this.ChildIcon = ChildIcon;}public int getNumber() {return Number;}public void setNumber(int Number) {this.Number = Number;}}
}
ExpandableListView适配器编写
自定义MyExpandableAdapter适配器继承BaseExpandableListAdapter,实现它的10个方法,基本上和ListView的适配器方法相同,可以看一下代码,注释很详细的,不过有几个方法需要注意一下:
getGroupView()方法
getGroupView()很重要,是需要重写的方法之一,用于获取给定分组的视图,它4有个参数,其中第二个参数isExpanded表示组item的展开状态,通过这个参数可以设置右侧的箭头图标变化。首先添加组item布局,通过groupPosition获取ExpandableMode实体对象,设置icon和名字,根据组item的状态设置右边箭头。getGropView完整代码如下:
/*** 获取给定分组的视图,主要重写的方法。** @param groupPosition groupPosition* @param isExpanded 该组是展开状态还是收起状态* @param convertView convertView* @param parent parent* @return View*/@Overridepublic View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {if (convertView == null) {convertView = LayoutInflater.from(mContext).inflate(R.layout.item_group, parent, false);}// 获取组的实体对象ExpandableMode expandableMode = mExpandableModeList.get(groupPosition);// 获取组名String groupName = expandableMode.getGroupName();// 获取组icon名字String iconName = expandableMode.getGroupIcon();// 调用getImageMipmapRes方法获取对应的icon资源int iconRes = getImageMipmapRes(mContext, iconName);// 获取Drawable对象Drawable drawableLeft = ContextCompat.getDrawable(mContext, iconRes);mViewHolder.setImage(convertView, R.id.item_group_icon_iv, drawableLeft);// 设置TextView的文字mViewHolder.setText(convertView, R.id.item_group_name_tv, groupName);// 设置组item展开或者关闭的右图片Drawable drawableRight = ContextCompat.getDrawable(mContext, R.mipmap.icon_right);if (isExpanded) {// 展开drawableRight = ContextCompat.getDrawable(mContext, R.mipmap.icon_down);}mViewHolder.setImageTextRight(convertView, R.id.item_group_name_tv, drawableRight);return convertView;}
在设置icon时调用了getImageMipmapRes方法,这个方法根据传入的图片名获取对应的图片资源:
/*** 通过文件名,获取对应的图片资源** @param context context* @param filename filename* @return 对应的图片资源*/public int getImageMipmapRes(Context context, String filename) {return context.getResources().getIdentifier(filename, "mipmap", context.getPackageName());}
getChildView()方法
getChildView()方法用于添加子item布局,和getGroupView()方法类似:
/*** 获取给定分组给定子位置的数据用的视图,主要重写的方法。** @param groupPosition groupPosition* @param childPosition childPosition* @param isLastChild 是否为改组最后一个子视图* @param convertView convertView* @param parent parent* @return View*/@Overridepublic View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {if (convertView == null) {convertView = LayoutInflater.from(mContext).inflate(R.layout.item_child, parent, false);}ExpandableMode expandableMode = mExpandableModeList.get(groupPosition);List<ExpandableMode.ChildDataBean> childDataBeans = expandableMode.getChildData();ExpandableMode.ChildDataBean childDataBean = childDataBeans.get(childPosition);// 获取子名字String childName = childDataBean.getChildName();// 获取对应的子iconString childIcon = childDataBean.getChildIcon();// 获取子icon名字对应的图片资源int childIconRes = getImageMipmapRes(mContext, childIcon);// 获取Drawable对象Drawable drawable = ContextCompat.getDrawable(mContext, childIconRes);// 设置iconmViewHolder.setImage(convertView, R.id.item_child_icon_iv, drawable);// 设置文字mViewHolder.setText(convertView, R.id.item_child_name_tv, childName);return convertView;}
isChildSelectable()方法
这个方法很重要,它用来判断子item是否可以点击,如果它返回false,子item将无法被点击,并且不会显示分割线,因此它应当设置返回true。
/*** 子item是否可点击* 当isChildSelectable方法返回false的时候,子item不可点击,且不会绘制分割线* @param groupPosition groupPosition* @param childPosition childPosition* @return true可点击 false不可点击*/@Overridepublic boolean isChildSelectable(int groupPosition, int childPosition) {return true;}
hasStableIds()方法
这个用来判断ExpandableListView内容id是否有效,我也不太明白它具体启什么作用,设置返回true和false的效果是一样的。
/*** 用来判断ExpandableListView内容id是否有效的,我也不太明白,它具体有什么作用,设置返回true和false的效果是一样的。** @return true or false*/@Overridepublic boolean hasStableIds() {return false;}
MyExpandableAdapter适配器的完整代码
MyExpandableAdapter适配器完整代码,ViewHolder请参适配器张神万能的适配器
package top.zhaohaibo.expandable.adapter;import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;import androidx.core.content.ContextCompat;import java.util.List;import top.zhaohaibo.expandable.R;
import top.zhaohaibo.expandable.mode.ExpandableMode;
import top.zhaohaibo.expandable.utils.ViewHolder;/*** 作者: Ocean
* 时间: 2020/3/28 9:37 PM
* 邮箱: xinzhaohaibo@aliyun.com
* 描述: 自定义可展开列表的适配器*/
public class MyExpandableAdapter extends BaseExpandableListAdapter {/** 数据集合 */private List<ExpandableMode> mExpandableModeList;/** 上下文 */private Context mContext;/** ViewHolder */private ViewHolder mViewHolder;public MyExpandableAdapter(List<ExpandableMode> expandableModeList, Context context) {mExpandableModeList = expandableModeList;mContext = context;mViewHolder = ViewHolder.getInstance();}/*** @return 返回组item数量*/@Overridepublic int getGroupCount() {return mExpandableModeList == null ? 0 : mExpandableModeList.size();}/*** 根据出入的组groupPosition返回子item的数量。** @param groupPosition groupPosition* @return 返回子item的数量。*/@Overridepublic int getChildrenCount(int groupPosition) {if (mExpandableModeList == null) return 0;List<ExpandableMode.ChildDataBean> childDataBeans = mExpandableModeList.get(groupPosition).getChildData();return childDataBeans == null ? 0 : childDataBeans.size();}/*** 获取组实体对象** @param groupPosition groupPosition* @return 返回组实体对象*/@Overridepublic Object getGroup(int groupPosition) {return mExpandableModeList == null ? null : mExpandableModeList.get(groupPosition);}/*** 获取子实体对象** @param groupPosition groupPosition* @param childPosition childPosition* @return 返回子实体对象*/@Overridepublic Object getChild(int groupPosition, int childPosition) {if (mExpandableModeList == null) return null;List<ExpandableMode.ChildDataBean> childDataBeans = mExpandableModeList.get(groupPosition).getChildData();return childDataBeans == null ? null : childDataBeans.get(childPosition);}/*** 获取组id,我理解为获取组的唯一ID,一般自己返回groupPosition即可** @param groupPosition groupPosition* @return Position*/@Overridepublic long getGroupId(int groupPosition) {return 0;}/*** 获取子ID** @param groupPosition groupPosition* @param childPosition childPosition* @return 返回子id*/@Overridepublic long getChildId(int groupPosition, int childPosition) {return 0;}/*** 用来判断ExpandableListView内容id是否有效的,我也不太明白,它具体有什么作用,设置返回true和false的效果是一样的。** @return true or false*/@Overridepublic boolean hasStableIds() {return false;}/*** 获取给定分组的视图,主要重写的方法。** @param groupPosition groupPosition* @param isExpanded 该组是展开状态还是收起状态* @param convertView convertView* @param parent parent* @return View*/@Overridepublic View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {if (convertView == null) {convertView = LayoutInflater.from(mContext).inflate(R.layout.item_group, parent, false);}// 获取组的实体对象ExpandableMode expandableMode = mExpandableModeList.get(groupPosition);// 获取组名String groupName = expandableMode.getGroupName();// 获取组icon名字String iconName = expandableMode.getGroupIcon();// 调用getImageMipmapRes方法获取对应的icon资源int iconRes = getImageMipmapRes(mContext, iconName);// 获取Drawable对象Drawable drawableLeft = ContextCompat.getDrawable(mContext, iconRes);mViewHolder.setImage(convertView, R.id.item_group_icon_iv, drawableLeft);// 设置TextView的文字mViewHolder.setText(convertView, R.id.item_group_name_tv, groupName);// 设置组item展开或者关闭的右图片Drawable drawableRight = ContextCompat.getDrawable(mContext, R.mipmap.icon_right);if (isExpanded) {// 展开drawableRight = ContextCompat.getDrawable(mContext, R.mipmap.icon_down);}mViewHolder.setImageTextRight(convertView, R.id.item_group_name_tv, drawableRight);return convertView;}/*** 获取给定分组给定子位置的数据用的视图,主要重写的方法。** @param groupPosition groupPosition* @param childPosition childPosition* @param isLastChild 是否为改组最后一个子视图* @param convertView convertView* @param parent parent* @return View*/@Overridepublic View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {if (convertView == null) {convertView = LayoutInflater.from(mContext).inflate(R.layout.item_child, parent, false);}ExpandableMode expandableMode = mExpandableModeList.get(groupPosition);List<ExpandableMode.ChildDataBean> childDataBeans = expandableMode.getChildData();ExpandableMode.ChildDataBean childDataBean = childDataBeans.get(childPosition);// 获取子名字String childName = childDataBean.getChildName();// 获取对应的子iconString childIcon = childDataBean.getChildIcon();// 获取子icon名字对应的图片资源int childIconRes = getImageMipmapRes(mContext, childIcon);// 获取Drawable对象Drawable drawable = ContextCompat.getDrawable(mContext, childIconRes);// 设置iconmViewHolder.setImage(convertView, R.id.item_child_icon_iv, drawable);// 设置文字mViewHolder.setText(convertView, R.id.item_child_name_tv, childName);return convertView;}/*** 子item是否可点击* 当isChildSelectable方法返回false的时候,子item不可点击,且不会绘制分割线** @param groupPosition groupPosition* @param childPosition childPosition* @return true可点击 false不可点击*/@Overridepublic boolean isChildSelectable(int groupPosition, int childPosition) {return true;}/*** 通过文件名,获取对应的图片资源** @param context context* @param filename filename* @return 对应的图片资源*/public int getImageMipmapRes(Context context, String filename) {return context.getResources().getIdentifier(filename, "mipmap", context.getPackageName());}
}
组item的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"><ImageViewandroid:id="@+id/item_group_icon_iv"android:layout_width="20dp"android:layout_height="20dp"android:layout_marginStart="5dp"android:scaleType="centerInside"android:src="@mipmap/icon_fruit"tools:ignore="ContentDescription" /><TextViewandroid:textColor="#000000"android:id="@+id/item_group_name_tv"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:drawableEnd="@mipmap/icon_right"android:drawablePadding="5dp"android:gravity="center_vertical"android:padding="8dp"android:text="水果"android:textSize="22sp" /></LinearLayout>
子item的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"><ImageViewandroid:id="@+id/item_child_icon_iv"android:layout_width="25dp"android:layout_height="25dp"android:layout_marginStart="35dp"android:scaleType="centerInside"android:src="@mipmap/icon_apple"tools:ignore="ContentDescription" /><TextViewandroid:layout_marginStart="5dp"android:id="@+id/item_child_name_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center_vertical"android:padding="5dp"android:text="苹果"android:textSize="25sp" /></LinearLayout>
ViewHolder完整代码
ViewHolder完整代码如下:
package top.zhaohaibo.expandable.utils;import android.graphics.drawable.Drawable;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;/*** 作者: Ocean
* 时间: 2020/3/28 9:57 PM
* 邮箱: xinzhaohaibo@aliyun.com
* 描述: ViewHolder* 见张神博客:https://blog.csdn.net/lmj623565791/article/details/38902805/*/
public class ViewHolder {/*** 静态内部类单例*/private static class SingleHolder {private static final ViewHolder sViewHolder = new ViewHolder();}/*** 获取SingleHolder实例** @return ViewHolder 对象*/public static ViewHolder getInstance() {return SingleHolder.sViewHolder;}/*** 私有的构造方法,避免这个类在外部被实例化*/private ViewHolder() {}/**** 获取资源对象* @param convertView 视图* @param id 控件ID* @param 泛型* @return 对应的视图类型*/ @SuppressWarnings("unchecked")public <T extends View> T get(View convertView, int id) {// 通过getTag获取控件view的标签,并强转成SparseArray对象,如果它为空这进行实例化,并把起设置成view的标签SparseArray<View> viewHolder = (SparseArray<View>) convertView.getTag();if (viewHolder == null) {viewHolder = new SparseArray<>();convertView.setTag(viewHolder);}View childView = viewHolder.get(id);if (childView == null) {childView = convertView.findViewById(id);viewHolder.put(id, childView);}return (T) childView;}/*** 设置文字** @param convertView 布局View* @param childViewId 子控件id* @param s 内容* @return ViewHolder*/public ViewHolder setText(View convertView, int childViewId, String s) {TextView textView = get(convertView, childViewId);textView.setText(s);return this;}/*** 设置文字** @param convertView 布局View* @param childViewId 子控件id* @param s 内容* @return ViewHolder*/public ViewHolder setText(View convertView, int childViewId, int s) {TextView textView = get(convertView, childViewId);textView.setText(s);return this;}/*** 设置图片** @param convertView 布局View* @param childViewId 子控件id* @param drawable drawable* @return ViewHolder*/public ViewHolder setImage(View convertView, int childViewId, Drawable drawable) {ImageView imageView = get(convertView, childViewId);imageView.setImageDrawable(drawable);return this;}/*** 设置图文数据** @param convertView 布局View* @param childViewId 子控件id* @param txt 文本* @param leftDrawable 左边图片* @param rightDrawable 右图片* @return ViewHolder ViewHolder*/public ViewHolder setImageText(View convertView, int childViewId, String txt, Drawable leftDrawable, Drawable rightDrawable) {TextView view = get(convertView, childViewId);if (isStrNull(txt)) {txt = "";}view.setText(txt);view.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, rightDrawable, null);return this;}/*** 设置文字的右图片** @param convertView 布局View* @param childViewId 子控件id* @return ViewHolder ViewHolder*/public ViewHolder setImageTextRight(View convertView, int childViewId, Drawable rightDrawable) {TextView view = get(convertView, childViewId);view.setCompoundDrawablesWithIntrinsicBounds(null, null, rightDrawable, null);return this;}/*** 空字符串判断** @param string 要判空的字符串* @return true 空串, false非空*/private boolean isStrNull(String string) {if (string == null || "null".equals(string) || "NULL".equals(string)) {return true;}// TextUtils.isEmpty(string);String str = string.replace(" ", "");return str.length() == 0;}}
主页面
ExpandableListView属性设置
主页面只有一个ExpandableListView控件,设置了四个属性,如下:
android:childDivider 设置子item的分割线;
android:divider 设置分割线的颜色;
android:dividerHeight 设置分割线的高度;
android:groupIndicator 隐藏左边默认的的Icon。
布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ExpandableListViewandroid:id="@+id/act_main_expandable_list_view"android:layout_width="match_parent"android:layout_height="match_parent"android:childDivider="@drawable/item_child_divider"android:divider="@color/item_line"android:dividerHeight="0.5dp"android:groupIndicator="@null" /></LinearLayout>
分割线
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"android:drawable="@color/item_line"android:insetLeft="40dp" />
ExpandableListView的数据刷新
ExpandableListView有两个重要方法,
collapseGroup(groupPosition);关闭某一组。
expandGroup(groupPosition);展开某一组。
依次调用他们可以实现数据刷新:
// 子item的监听mExpandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {@Overridepublic boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {Toast.makeText(MainActivity.this, childPosition + "", Toast.LENGTH_SHORT).show();List<ExpandableMode.ChildDataBean> childDataBeans = mExpandableModeList.get(groupPosition).getChildData();childDataBeans.add(childDataBeans.get(childPosition));// 设置数据mExpandableAdapter.setExpandableModeList(mExpandableModeList);// 通过关闭组item在展开刷新数据mExpandableListView.collapseGroup(groupPosition);mExpandableListView.expandGroup(groupPosition);return false;}});
设置默认展开全部
// 打开所有for (int i = 0; i < mExpandableModeList.size(); i++) mExpandableListView.expandGroup(i);// 设置默认展开蔬菜组// mExpandableListView.expandGroup(1);
主页面完整代码
package top.zhaohaibo.expandable;import androidx.appcompat.app.AppCompatActivity;import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.Toast;import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;import top.zhaohaibo.expandable.adapter.MyExpandableAdapter;
import top.zhaohaibo.expandable.mode.ExpandableMode;/*** 作者: Ocean
* 时间: 2020/3/28 9:57 PM
* 邮箱: xinzhaohaibo@aliyun.com
* 描述: git pull origin master --allow-unrelated-histories*/
public class MainActivity extends AppCompatActivity {/** 数据集合 */private List<ExpandableMode> mExpandableModeList;/** 适配器 */private MyExpandableAdapter mExpandableAdapter;/** 可展开的List */private ExpandableListView mExpandableListView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mExpandableListView = findViewById(R.id.act_main_expandable_list_view);// 调用readAssetsFile方法读取assets下的测试数据String ExpandableModeStr = readAssetsFile("ExpandableMode.json", this);Gson gson = new Gson();// 通过Gson把读到的ExpandableModeStr转换为实体对象mExpandableModeList = gson.fromJson(ExpandableModeStr, new TypeToken<List<ExpandableMode>>() {}.getType());// 实例化适配器mExpandableAdapter = new MyExpandableAdapter(mExpandableModeList, this);// 设置适配器mExpandableListView.setAdapter(mExpandableAdapter);// 子item的监听mExpandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {@Overridepublic boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {Toast.makeText(MainActivity.this, childPosition + "", Toast.LENGTH_SHORT).show();List<ExpandableMode.ChildDataBean> childDataBeans = mExpandableModeList.get(groupPosition).getChildData();childDataBeans.add(childDataBeans.get(childPosition));// 设置数据mExpandableAdapter.setExpandableModeList(mExpandableModeList);// 通过关闭组item在展开刷新数据mExpandableListView.collapseGroup(groupPosition);mExpandableListView.expandGroup(groupPosition);return false;}});// 打开所有for (int i = 0; i < mExpandableModeList.size(); i++) mExpandableListView.expandGroup(i);// 设置默认展开蔬菜组// mExpandableListView.expandGroup(1);}/*** 读取assets中的文件 流程* readAssetsFile("json/xx.json", this);** @param fileName 文件名* @param context context* @return 读取的内容*/public String readAssetsFile(String fileName, Context context) {// 输入流对象InputStream inputStream;// 缓存流对象BufferedReader bufferedReader = null;StringBuilder stringBuilder = new StringBuilder();try {// getAssets方法返回通过输入流对象inputStream = context.getAssets().open(fileName);// InputStreamReader 实现字节流到字符流的转换bufferedReader = new BufferedReader(new InputStreamReader(inputStream));String line;while ((line = bufferedReader.readLine()) != null) {stringBuilder.append(line);}} catch (IOException e) {Log.e("MainActivity", e.toString());} finally {try {if (bufferedReader != null) {bufferedReader.close();}} catch (IOException e) {Log.e("MainActivity", e.toString());}}return stringBuilder.toString();}
}
源码
Demo源码(喜欢点个星)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
