如何从含String类型ArrayList成员的类填充ListView及应用实现问题
嘿,我来帮你搞定这个ListView填充的问题!先提个小细节:你写的Application类构造函数里有个笔误——this.title = imageName;应该改成this.title = title;,不然标题会赋值错误,先修正这个小问题哦。
下面是完整的实现步骤:
一、先搞定列表项的布局
首先创建单个应用项的布局文件res/layout/item_app.xml,用来展示应用图标、标题和版本列表:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:orientation="horizontal" android:gravity="center_vertical"> <!-- 应用图标 --> <ImageView android:id="@+id/iv_app_icon" android:layout_width="48dp" android:layout_height="48dp" android:scaleType="centerCrop"/> <!-- 标题和版本信息容器 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginStart="16dp"> <TextView android:id="@+id/tv_app_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:textStyle="bold"/> <TextView android:id="@+id/tv_app_versions" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="14sp" android:textColor="@android:color/darker_gray" android:layout_marginTop="4dp"/> </LinearLayout> </LinearLayout>
二、自定义ListView的Adapter
写一个继承自BaseAdapter的适配器,用来把Application数据和布局绑定,同时优化ListView的性能:
import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; import java.util.ArrayList; public class AppListAdapter extends BaseAdapter { private Context mContext; private ArrayList<Application> mAppList; private LayoutInflater mInflater; // 构造函数:传入上下文和应用数据列表 public AppListAdapter(Context context, ArrayList<Application> appList) { mContext = context; mAppList = appList; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return mAppList.size(); } @Override public Object getItem(int position) { return mAppList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; // 复用convertView优化性能 if (convertView == null) { convertView = mInflater.inflate(R.layout.item_app, parent, false); holder = new ViewHolder(); holder.appIcon = convertView.findViewById(R.id.iv_app_icon); holder.appTitle = convertView.findViewById(R.id.tv_app_title); holder.appVersions = convertView.findViewById(R.id.tv_app_versions); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // 获取当前位置的应用数据 Application currentApp = mAppList.get(position); // 设置标题 holder.appTitle.setText(currentApp.getTitle()); // 把版本列表转成逗号分隔的字符串展示 String versionStr = String.join(", ", currentApp.getAppVersions()); holder.appVersions.setText("版本:" + versionStr); // 加载网络图片(这里用Glide,需要添加依赖) Glide.with(mContext) .load(currentApp.getImageUrl()) .placeholder(R.drawable.ic_default_app) // 加载中的占位图 .error(R.drawable.ic_error) // 加载失败的图 .into(holder.appIcon); return convertView; } // ViewHolder类:缓存控件,避免重复findViewById static class ViewHolder { ImageView appIcon; TextView appTitle; TextView appVersions; } }
三、在主Activity中初始化ListView并设置点击事件
假设你的主Activity是MainActivity,这里完成数据初始化、Adapter设置和点击跳转逻辑:
import android.content.Intent; import android.os.Bundle; import android.widget.ListView; import androidx.appcompat.app.AppCompatActivity; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private ListView mAppListView; private ArrayList<Application> mAppDataList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化ListView控件 mAppListView = findViewById(R.id.lv_app_list); // 模拟测试数据 mAppDataList = new ArrayList<>(); ArrayList<String> versions1 = new ArrayList<>(); versions1.add("1.0.0"); versions1.add("1.1.0"); versions1.add("2.0.0"); mAppDataList.add(new Application("我的应用1", "https://example.com/icon1.png", versions1)); ArrayList<String> versions2 = new ArrayList<>(); versions2.add("3.2.1"); versions2.add("3.3.0"); mAppDataList.add(new Application("我的应用2", "https://example.com/icon2.png", versions2)); // 设置Adapter AppListAdapter adapter = new AppListAdapter(this, mAppDataList); mAppListView.setAdapter(adapter); // 列表项点击事件:跳转到应用信息Activity mAppListView.setOnItemClickListener((parent, view, position, id) -> { Application clickedApp = mAppDataList.get(position); // 创建跳转Intent Intent intent = new Intent(MainActivity.this, AppInfoActivity.class); // 传递应用数据(这里用Parcelable更高效,后面会补充) intent.putExtra("APP_TITLE", clickedApp.getTitle()); intent.putExtra("APP_IMAGE_URL", clickedApp.getImageUrl()); intent.putExtra("APP_VERSIONS", clickedApp.getAppVersions()); startActivity(intent); }); } }
四、在应用信息Activity中接收并展示数据
创建AppInfoActivity,获取传递过来的应用数据并展示:
import android.os.Bundle; import android.widget.ImageView; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import com.bumptech.glide.Glide; import java.util.ArrayList; public class AppInfoActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_app_info); TextView tvTitle = findViewById(R.id.tv_info_title); ImageView ivIcon = findViewById(R.id.iv_info_icon); TextView tvVersions = findViewById(R.id.tv_info_versions); // 获取Intent传递的数据 String title = getIntent().getStringExtra("APP_TITLE"); String imageUrl = getIntent().getStringExtra("APP_IMAGE_URL"); ArrayList<String> versions = getIntent().getStringArrayListExtra("APP_VERSIONS"); // 展示数据 tvTitle.setText(title); Glide.with(this) .load(imageUrl) .placeholder(R.drawable.ic_default_app) .into(ivIcon); // 换行展示每个版本 String versionStr = String.join("\n", versions); tvVersions.setText("版本历史:\n" + versionStr); } }
补充优化建议
- 图片加载依赖:上面用了Glide加载网络图片,需要在模块级
build.gradle添加依赖:
dependencies { implementation 'com.github.bumptech.glide:glide:4.16.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' }
- 高效数据传递:如果
Application类字段较多,推荐让它实现Parcelable接口,这样传递整个对象更高效。修改后的Application类如下:
import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; public class Application implements Parcelable { private String title; private String imageUrl; private ArrayList<String> appVersions; public Application(String title, String imageUrl, ArrayList<String> appVersions) { this.title = title; this.imageUrl = imageUrl; this.appVersions = appVersions; } // Parcelable实现代码 protected Application(Parcel in) { title = in.readString(); imageUrl = in.readString(); appVersions = in.createStringArrayList(); } public static final Creator<Application> CREATOR = new Creator<Application>() { @Override public Application createFromParcel(Parcel in) { return new Application(in); } @Override public Application[] newArray(int size) { return new Application[size]; } }; // 原有getter方法 public String getTitle() { return title; } public String getImageUrl() { return imageUrl; } public ArrayList<String> getAppVersions() { return appVersions; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(title); dest.writeString(imageUrl); dest.writeStringList(appVersions); } }
此时点击事件传递数据可以简化为:
intent.putExtra("APP_DATA", clickedApp);
在AppInfoActivity中获取:
Application app = getIntent().getParcelableExtra("APP_DATA");
内容的提问来源于stack exchange,提问作者Shark
相关产品推荐
相关产品推荐

