
最近在开发世界杯主题应用时发现传统静态阵容展示已经无法满足用户需求。球迷们不仅想看到首发阵容名单更希望直观感受球员风采和战术布局。本文将结合最新的Nano Banana 2 Lite和Gemini Omni Flash技术打造一个能够动态生成球员形象和战术动画的世界杯首发阵容App。这个项目适合有一定Android开发基础想要探索AI图像生成和视频编辑技术的开发者。通过本文你将掌握如何将两种AI模型无缝集成到移动应用中实现从文本描述到生动视频的完整创作流程。1. 技术背景与核心概念1.1 Nano Banana 2 Lite技术解析Nano Banana 2 Lite是Google最新推出的轻量级图像生成模型专门为移动端和高并发场景优化。该模型基于Gemini 3.1 Flash Lite Image架构在保持高质量图像生成的同时显著降低了计算资源和响应时间。在实际测试中Nano Banana 2 Lite生成一张1024x1024分辨率图像仅需4秒左右成本为每千张图像0.034美元。这种性能表现使其非常适合实时交互应用比如我们的世界杯阵容App需要快速生成多个球员形象。与之前的版本相比Nano Banana 2 Lite在提示词遵循度和字符一致性方面有显著提升。这意味着当我们用生成梅西穿着阿根廷队服的比赛照片这样的提示词时模型能够准确理解足球相关的专业术语和视觉特征。1.2 Gemini Omni Flash视频生成能力Gemini Omni Flash是多模态视频生成模型支持文本、图像和视频的混合输入。在我们的世界杯App中它将负责把静态的球员图像转化为生动的比赛片段。该模型的核心优势在于对话式视频编辑能力。用户可以用自然语言指令如让梅西带球突破防守来指导视频生成过程模型会基于对足球运动的理解生成相应的动画效果。目前Omni Flash支持最长10秒的视频生成正好适合展示球员的典型技术动作。每秒钟视频生成成本为0.10美元对于短片段展示来说成本可控。1.3 技术组合的价值主张将Nano Banana 2 Lite和Gemini Omni Flash结合使用可以创建完整的多媒体内容生产流水线。这种组合特别适合需要快速原型开发和内容迭代的场景。在我们的世界杯App中工作流程将是首先用Nano Banana 2 Lite根据球员信息生成标准肖像然后使用Gemini Omni Flash为每个球员创建特色技术动作视频最后将所有内容整合成交互式阵容展示。2. 开发环境准备2.1 基础开发环境配置为了确保项目顺利进行需要准备以下开发环境操作系统要求Windows 10/11 或 macOS 12.0 或 Ubuntu 20.04至少8GB RAM推荐16GB10GB可用磁盘空间开发工具Android Studio 2023.2.1Java Development Kit 17Android SDK API 34依赖管理使用Gradle进行依赖管理确保网络连接稳定以便下载相关SDK。2.2 API密钥获取与配置访问Google AI Studio获取必要的API密钥前往 Google AI Studio使用Google账户登录在控制台创建新项目启用Gemini API服务生成API密钥在项目的local.properties文件中安全存储API密钥gemini.api.key你的API密钥 nanobanana.api.key你的Nano Banana API密钥2.3 项目基础结构搭建创建新的Android项目选择Empty Activity模板。配置app级别的build.gradle文件android { compileSdk 34 defaultConfig { applicationId com.worldcup.lineup minSdk 24 targetSdk 34 versionCode 1 versionName 1.0 testInstrumentationRunner androidx.test.runner.AndroidJUnitRunner } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile(proguard-android-optimize.txt), proguard-rules.pro } } compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } } dependencies { implementation androidx.core:core-ktx:1.12.0 implementation androidx.appcompat:appcompat:1.6.1 implementation com.google.android.material:material:1.10.0 implementation androidx.constraintlayout:constraintlayout:2.1.4 // 网络请求库 implementation com.squareup.retrofit2:retrofit:2.9.0 implementation com.squareup.retrofit2:converter-gson:2.9.0 implementation com.squareup.okhttp3:logging-interceptor:4.11.0 // 图像加载库 implementation com.github.bumptech.glide:glide:4.15.1 // 视频播放库 implementation com.google.android.exoplayer:exoplayer:2.19.1 testImplementation junit:junit:4.13.2 androidTestImplementation androidx.test.ext:junit:1.1.5 androidTestImplementation androidx.test.espresso:espresso-core:3.5.1 }3. 核心功能实现3.1 Nano Banana 2 Lite图像生成集成首先创建API服务接口用于调用Nano Banana 2 Lite// 文件路径app/src/main/java/com/worldcup/lineup/api/NanoBananaService.java public interface NanoBananaService { POST(v1/images:generate) CallImageResponse generateImage(Body ImageRequest request); Headers(Content-Type: application/json) class ImageRequest { private final ImagePrompt prompt; private final int width; private final int height; public ImageRequest(ImagePrompt prompt, int width, int height) { this.prompt prompt; this.width width; this.height height; } } class ImagePrompt { private final String text; public ImagePrompt(String text) { this.text text; } } class ImageResponse { private ListImageData images; public ListImageData getImages() { return images; } class ImageData { private String base64Data; public String getBase64Data() { return base64Data; } } } }实现球员图像生成工具类// 文件路径app/src/main/java/com/worldcup/lineup/utils/PlayerImageGenerator.java public class PlayerImageGenerator { private static final String BASE_URL https://generativelanguage.googleapis.com/; private final NanoBananaService service; private final String apiKey; public PlayerImageGenerator(Context context) { this.apiKey getApiKey(context); Retrofit retrofit new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(createHttpClient()) .build(); this.service retrofit.create(NanoBananaService.class); } public void generatePlayerImage(String playerName, String team, String position, ImageGenerationCallback callback) { String prompt buildPlayerPrompt(playerName, team, position); NanoBananaService.ImageRequest request new NanoBananaService.ImageRequest( new NanoBananaService.ImagePrompt(prompt), 512, 512); service.generateImage(request).enqueue(new CallbackNanoBananaService.ImageResponse() { Override public void onResponse(CallNanoBananaService.ImageResponse call, ResponseNanoBananaService.ImageResponse response) { if (response.isSuccessful() response.body() ! null) { ListNanoBananaService.ImageResponse.ImageData images response.body().getImages(); if (images ! null !images.isEmpty()) { String base64Image images.get(0).getBase64Data(); callback.onSuccess(base64Image); return; } } callback.onError(图像生成失败); } Override public void onFailure(CallNanoBananaService.ImageResponse call, Throwable t) { callback.onError(网络请求失败: t.getMessage()); } }); } private String buildPlayerPrompt(String playerName, String team, String position) { return String.format( 生成%s队%s球员%s的专业足球比赛照片。穿着正式比赛队服在绿茵场上展现足球运动员的专业姿态。背景为体育场光线自然图像清晰。, team, position, playerName ); } public interface ImageGenerationCallback { void onSuccess(String base64Image); void onError(String errorMessage); } }3.2 Gemini Omni Flash视频生成集成创建视频生成服务接口// 文件路径app/src/main/java/com/worldcup/lineup/api/OmniFlashService.java public interface OmniFlashService { POST(v1/videos:generate) CallVideoResponse generateVideo(Body VideoRequest request); class VideoRequest { private final VideoPrompt prompt; private final int durationSeconds; public VideoRequest(VideoPrompt prompt, int durationSeconds) { this.prompt prompt; this.durationSeconds durationSeconds; } } class VideoPrompt { private final String text; private final String imageReference; public VideoPrompt(String text, String imageReference) { this.text text; this.imageReference imageReference; } } class VideoResponse { private VideoData video; public VideoData getVideo() { return video; } class VideoData { private String videoUri; private int duration; public String getVideoUri() { return videoUri; } } } }实现球员动作视频生成器// 文件路径app/src/main/java/com/worldcup/lineup/utils/PlayerVideoGenerator.java public class PlayerVideoGenerator { private static final String BASE_URL https://generativelanguage.googleapis.com/; private final OmniFlashService service; private final String apiKey; public PlayerVideoGenerator(Context context) { this.apiKey getApiKey(context); Retrofit retrofit new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(createHttpClient()) .build(); this.service retrofit.create(OmniFlashService.class); } public void generatePlayerVideo(String playerName, String position, String base64Image, VideoGenerationCallback callback) { String prompt buildVideoPrompt(playerName, position); OmniFlashService.VideoRequest request new OmniFlashService.VideoRequest( new OmniFlashService.VideoPrompt(prompt, base64Image), 5); service.generateVideo(request).enqueue(new CallbackOmniFlashService.VideoResponse() { Override public void onResponse(CallOmniFlashService.VideoResponse call, ResponseOmniFlashService.VideoResponse response) { if (response.isSuccessful() response.body() ! null) { OmniFlashService.VideoResponse.VideoData video response.body().getVideo(); if (video ! null) { callback.onSuccess(video.getVideoUri()); return; } } callback.onError(视频生成失败); } Override public void onFailure(CallOmniFlashService.VideoResponse call, Throwable t) { callback.onError(网络请求失败: t.getMessage()); } }); } private String buildVideoPrompt(String playerName, String position) { MapString, String positionActions new HashMap(); positionActions.put(前锋, 展示射门和突破动作); positionActions.put(中场, 展示传球和组织进攻动作); positionActions.put(后卫, 展示抢断和防守动作); positionActions.put(守门员, 展示扑救动作); String action positionActions.getOrDefault(position, 展示足球技术动作); return String.format(让%s在足球比赛中%s。画面流畅自然展现专业足球运动员的技术特点。, playerName, action); } public interface VideoGenerationCallback { void onSuccess(String videoUri); void onError(String errorMessage); } }3.3 数据模型设计定义球员和阵容的数据结构// 文件路径app/src/main/java/com/worldcup/lineup/models/Player.java public class Player { private String id; private String name; private String team; private String position; private int jerseyNumber; private String imageUrl; private String videoUrl; private boolean isCaptain; private MapString, Object stats; public Player(String name, String team, String position, int jerseyNumber) { this.name name; this.team team; this.position position; this.jerseyNumber jerseyNumber; this.stats new HashMap(); } // Getter和Setter方法 public String getName() { return name; } public void setName(String name) { this.name name; } public String getTeam() { return team; } public void setTeam(String team) { this.team team; } public String getPosition() { return position; } public void setPosition(String position) { this.position position; } public int getJerseyNumber() { return jerseyNumber; } public void setJerseyNumber(int jerseyNumber) { this.jerseyNumber jerseyNumber; } public String getImageUrl() { return imageUrl; } public void setImageUrl(String imageUrl) { this.imageUrl imageUrl; } public String getVideoUrl() { return videoUrl; } public void setVideoUrl(String videoUrl) { this.videoUrl videoUrl; } public boolean isCaptain() { return isCaptain; } public void setCaptain(boolean captain) { isCaptain captain; } public MapString, Object getStats() { return stats; } public void setStats(MapString, Object stats) { this.stats stats; } } // 文件路径app/src/main/java/com/worldcup/lineup/models/Lineup.java public class Lineup { private String team; private String formation; private ListPlayer players; private Date matchDate; private String opponent; public Lineup(String team, String formation) { this.team team; this.formation formation; this.players new ArrayList(); } public void addPlayer(Player player) { players.add(player); } public ListPlayer getPlayersByPosition(String position) { return players.stream() .filter(player - position.equals(player.getPosition())) .collect(Collectors.toList()); } // Getter和Setter方法 public String getTeam() { return team; } public void setTeam(String team) { this.team team; } public String getFormation() { return formation; } public void setFormation(String formation) { this.formation formation; } public ListPlayer getPlayers() { return players; } public void setPlayers(ListPlayer players) { this.players players; } public Date getMatchDate() { return matchDate; } public void setMatchDate(Date matchDate) { this.matchDate matchDate; } public String getOpponent() { return opponent; } public void setOpponent(String opponent) { this.opponent opponent; } }4. 用户界面设计与实现4.1 主界面布局设计创建主Activity的布局文件展示球队阵容!-- 文件路径app/src/main/res/layout/activity_main.xml -- LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/android android:layout_widthmatch_parent android:layout_heightmatch_parent android:orientationvertical android:backgroundcolor/background com.google.android.material.appbar.MaterialToolbar android:idid/toolbar android:layout_widthmatch_parent android:layout_height?attr/actionBarSize android:backgroundcolor/primary android:themestyle/ThemeOverlay.Material3.Dark.ActionBar / ScrollView android:layout_widthmatch_parent android:layout_height0dp android:layout_weight1 android:padding16dp LinearLayout android:layout_widthmatch_parent android:layout_heightwrap_content android:orientationvertical !-- 球队信息 -- LinearLayout android:layout_widthmatch_parent android:layout_heightwrap_content android:orientationhorizontal android:gravitycenter_vertical android:paddingBottom16dp ImageView android:idid/team_logo android:layout_width48dp android:layout_height48dp android:srcdrawable/ic_team_default / TextView android:idid/team_name android:layout_width0dp android:layout_heightwrap_content android:layout_weight1 android:layout_marginStart16dp android:textSize24sp android:textStylebold android:textColorcolor/text_primary / TextView android:idid/formation android:layout_widthwrap_content android:layout_heightwrap_content android:textSize16sp android:backgrounddrawable/formation_badge android:padding8dp android:textColorcolor/white / /LinearLayout !-- 阵容展示区域 -- TextView android:layout_widthmatch_parent android:layout_heightwrap_content android:text首发阵容 android:textSize20sp android:textStylebold android:paddingBottom8dp / androidx.recyclerview.widget.RecyclerView android:idid/players_recycler android:layout_widthmatch_parent android:layout_heightwrap_content android:layout_marginBottom16dp / !-- 生成按钮 -- com.google.android.material.button.MaterialButton android:idid/generate_button android:layout_widthmatch_parent android:layout_heightwrap_content android:text生成阵容展示 android:textSize16sp stylestyle/Widget.Material3.Button / /LinearLayout /ScrollView /LinearLayout4.2 球员列表适配器实现创建RecyclerView适配器来展示球员列表// 文件路径app/src/main/java/com/worldcup/lineup/adapters/PlayerAdapter.java public class PlayerAdapter extends RecyclerView.AdapterPlayerAdapter.PlayerViewHolder { private final ListPlayer players; private final OnPlayerClickListener listener; public PlayerAdapter(ListPlayer players, OnPlayerClickListener listener) { this.players players; this.listener listener; } NonNull Override public PlayerViewHolder onCreateViewHolder(NonNull ViewGroup parent, int viewType) { View view LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_player, parent, false); return new PlayerViewHolder(view); } Override public void onBindViewHolder(NonNull PlayerViewHolder holder, int position) { Player player players.get(position); holder.bind(player, listener); } Override public int getItemCount() { return players.size(); } static class PlayerViewHolder extends RecyclerView.ViewHolder { private final ImageView playerImage; private final TextView playerName; private final TextView playerPosition; private final TextView jerseyNumber; private final ImageView captainBadge; public PlayerViewHolder(NonNull View itemView) { super(itemView); playerImage itemView.findViewById(R.id.player_image); playerName itemView.findViewById(R.id.player_name); playerPosition itemView.findViewById(R.id.player_position); jerseyNumber itemView.findViewById(R.id.jersey_number); captainBadge itemView.findViewById(R.id.captain_badge); } public void bind(Player player, OnPlayerClickListener listener) { playerName.setText(player.getName()); playerPosition.setText(player.getPosition()); jerseyNumber.setText(String.valueOf(player.getJerseyNumber())); if (player.isCaptain()) { captainBadge.setVisibility(View.VISIBLE); } else { captainBadge.setVisibility(View.GONE); } // 加载球员图像 if (player.getImageUrl() ! null) { Glide.with(itemView.getContext()) .load(player.getImageUrl()) .placeholder(R.drawable.ic_player_placeholder) .into(playerImage); } itemView.setOnClickListener(v - { if (listener ! null) { listener.onPlayerClick(player); } }); } } public interface OnPlayerClickListener { void onPlayerClick(Player player); } }4.3 球员详情页面实现创建球员详情页面展示生成的图像和视频// 文件路径app/src/main/java/com/worldcup/lineup/ui/PlayerDetailActivity.java public class PlayerDetailActivity extends AppCompatActivity { private static final String EXTRA_PLAYER extra_player; private Player player; private ImageView playerImageView; private VideoView playerVideoView; private ProgressBar loadingProgress; private Button playVideoButton; public static void start(Context context, Player player) { Intent intent new Intent(context, PlayerDetailActivity.class); intent.putExtra(EXTRA_PLAYER, player); context.startActivity(intent); } Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player_detail); initViews(); loadPlayerData(); setupVideoPlayer(); } private void initViews() { playerImageView findViewById(R.id.player_image); playerVideoView findViewById(R.id.player_video); loadingProgress findViewById(R.id.loading_progress); playVideoButton findViewById(R.id.play_video_button); // 设置工具栏 MaterialToolbar toolbar findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } private void loadPlayerData() { player getIntent().getParcelableExtra(EXTRA_PLAYER); if (player null) { finish(); return; } setTitle(player.getName()); // 显示球员图像 if (player.getImageUrl() ! null) { Glide.with(this) .load(player.getImageUrl()) .into(playerImageView); } // 如果有视频URL显示播放按钮 if (player.getVideoUrl() ! null) { playVideoButton.setVisibility(View.VISIBLE); } else { playVideoButton.setVisibility(View.GONE); } } private void setupVideoPlayer() { playVideoButton.setOnClickListener(v - { if (player.getVideoUrl() ! null) { playVideo(player.getVideoUrl()); } }); } private void playVideo(String videoUrl) { loadingProgress.setVisibility(View.VISIBLE); playerVideoView.setVisibility(View.VISIBLE); MediaController mediaController new MediaController(this); mediaController.setAnchorView(playerVideoView); playerVideoView.setMediaController(mediaController); playerVideoView.setVideoURI(Uri.parse(videoUrl)); playerVideoView.setOnPreparedListener(mp - { loadingProgress.setVisibility(View.GONE); playerVideoView.start(); }); playerVideoView.setOnErrorListener((mp, what, extra) - { loadingProgress.setVisibility(View.GONE); Toast.makeText(this, 视频播放失败, Toast.LENGTH_SHORT).show(); return true; }); } Override public boolean onSupportNavigateUp() { onBackPressed(); return true; } }5. 核心业务逻辑整合5.1 阵容生成管理器创建阵容生成的核心管理类协调图像和视频生成流程// 文件路径app/src/main/java/com/worldcup/lineup/core/LineupGenerator.java public class LineupGenerator { private final Context context; private final PlayerImageGenerator imageGenerator; private final PlayerVideoGenerator videoGenerator; private final ExecutorService executorService; public LineupGenerator(Context context) { this.context context.getApplicationContext(); this.imageGenerator new PlayerImageGenerator(context); this.videoGenerator new PlayerVideoGenerator(context); this.executorService Executors.newFixedThreadPool(3); } public void generateCompleteLineup(Lineup lineup, GenerationCallback callback) { executorService.execute(() - { try { ListPlayer players lineup.getPlayers(); CountDownLatch latch new CountDownLatch(players.size()); AtomicInteger successCount new AtomicInteger(0); AtomicInteger errorCount new AtomicInteger(0); for (Player player : players) { generatePlayerContent(player, new PlayerGenerationCallback() { Override public void onSuccess(Player updatedPlayer) { successCount.incrementAndGet(); latch.countDown(); checkCompletion(players.size(), successCount.get(), errorCount.get(), callback); } Override public void onError(String error) { errorCount.incrementAndGet(); latch.countDown(); checkCompletion(players.size(), successCount.get(), errorCount.get(), callback); } }); } // 设置超时时间 boolean completed latch.await(5, TimeUnit.MINUTES); if (!completed) { callback.onError(生成超时); } } catch (InterruptedException e) { callback.onError(生成过程被中断); } }); } private void generatePlayerContent(Player player, PlayerGenerationCallback callback) { // 首先生成图像 imageGenerator.generatePlayerImage( player.getName(), player.getTeam(), player.getPosition(), new PlayerImageGenerator.ImageGenerationCallback() { Override public void onSuccess(String base64Image) { // 保存图像 String imageUrl saveImage(base64Image, player.getName()); player.setImageUrl(imageUrl); // 然后生成视频 generatePlayerVideo(player, base64Image, callback); } Override public void onError(String errorMessage) { callback.onError(图像生成失败: errorMessage); } } ); } private void generatePlayerVideo(Player player, String base64Image, PlayerGenerationCallback callback) { videoGenerator.generatePlayerVideo( player.getName(), player.getPosition(), base64Image, new PlayerVideoGenerator.VideoGenerationCallback() { Override public void onSuccess(String videoUri) { player.setVideoUrl(videoUri); callback.onSuccess(player); } Override public void onError(String errorMessage) { // 视频生成失败不影响整体流程只记录错误 Log.w(LineupGenerator, 视频生成失败: errorMessage); callback.onSuccess(player); // 仍然认为成功只是没有视频 } } ); } private String saveImage(String base64Image, String playerName) { try { byte[] imageData Base64.decode(base64Image, Base64.DEFAULT); File imageFile new File(context.getFilesDir(), player_ playerName _ System.currentTimeMillis() .jpg); try (FileOutputStream fos new FileOutputStream(imageFile)) { fos.write(imageData); } return imageFile.getAbsolutePath(); } catch (IOException e) { Log.e(LineupGenerator, 保存图像失败, e); return null; } } private void checkCompletion(int total, int success, int error, GenerationCallback callback) { if (success error total) { if (success 0) { callback.onSuccess(success, error); } else { callback.onError(所有球员内容生成失败); } } } public interface GenerationCallback { void onSuccess(int successCount, int errorCount); void onError(String errorMessage); } public interface PlayerGenerationCallback { void onSuccess(Player player); void onError(String error); } }5.2 主Activity业务逻辑实现主Activity的完整业务逻辑// 文件路径app/src/main/java/com/worldcup/lineup/ui/MainActivity.java public class MainActivity extends AppCompatActivity { private LineupGenerator lineupGenerator; private PlayerAdapter playerAdapter; private Lineup currentLineup; private RecyclerView playersRecycler; private MaterialButton generateButton; private ProgressDialog progressDialog; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); setupLineupGenerator(); loadSampleData(); setupRecyclerView(); } private void initViews() { playersRecycler findViewById(R.id.players_recycler); generateButton findViewById(R.id.generate_button); generateButton.setOnClickListener(v - generateLineupContent()); // 设置工具栏 MaterialToolbar toolbar findViewById(R.id.toolbar); setSupportActionBar(toolbar); } private void setupLineupGenerator() { lineupGenerator new LineupGenerator(this); } private void loadSampleData() { // 创建示例阵容数据 currentLineup new Lineup(阿根廷, 4-3-3); currentLineup.setOpponent(法国); currentLineup.setMatchDate(new Date()); // 添加示例球员 currentLineup.addPlayer(new Player(梅西, 阿根廷, 前锋, 10)); currentLineup.addPlayer(new Player(迪玛利亚, 阿根廷, 前锋, 11)); currentLineup.addPlayer(new Player(阿尔瓦雷斯, 阿根廷, 前锋, 9)); currentLineup.addPlayer(new Player(德保罗, 阿根廷, 中场, 7)); currentLineup.addPlayer(new Player(恩佐, 阿根廷, 中场, 24)); currentLineup.addPlayer(new Player(麦卡利斯特, 阿根廷, 中场, 20)); currentLineup.addPlayer(new Player(莫利纳, 阿根廷, 后卫, 26)); currentLineup.addPlayer(new Player(罗梅罗, 阿根廷, 后卫, 13)); currentLineup.addPlayer(new Player(奥塔门迪, 阿根廷, 后卫, 19)); currentLineup.addPlayer(new Player(阿库尼亚, 阿根廷, 后卫, 8)); currentLineup.addPlayer(new Player(马丁内斯, 阿根廷, 守门员, 23)); // 设置队长 currentLineup.getPlayers().get(0).setCaptain(true); updateUI(); } private void setupRecyclerView() { playersRecycler.setLayoutManager(new LinearLayoutManager(this)); playerAdapter new PlayerAdapter(currentLineup.getPlayers(), new PlayerAdapter.OnPlayerClickListener() { Override public void onPlayerClick(Player player) { PlayerDetailActivity.start(MainActivity.this, player); } }); playersRecycler.setAdapter(playerAdapter); } private void generateLineupContent() { if (currentLineup null) return; progressDialog new ProgressDialog(this); progressDialog.setMessage(正在生成球员图像和视频...); progressDialog.setCancelable(false); progressDialog.show(); lineupGenerator.generateCompleteLineup(currentLineup, new LineupGenerator.GenerationCallback() { Override public void onSuccess(int successCount, int errorCount) { runOnUiThread(() - { if (progressDialog ! null progressDialog.isShowing()) { progressDialog.dismiss(); } String message String.format( 生成完成成功%d个失败%d个, successCount, errorCount); Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show(); updateUI(); }); } Override public void onError(String errorMessage) { runOnUiThread(() - { if (progressDialog ! null progressDialog.isShowing()) { progressDialog.dismiss(); } Toast.makeText(MainActivity.this, 生成失败: errorMessage, Toast.LENGTH_LONG).show(); }); } }); } private void updateUI() { if (playerAdapter ! null) { playerAdapter.notifyDataSetChanged(); } // 更新球队信息 TextView teamName findViewById(R.id.team_name); TextView formation findViewById(R.id.formation); if (teamName ! null) { teamName.setText(currentLineup.getTeam()); } if (formation ! null) { formation.setText(currentLineup.getFormation()); } } Override protected void onDestroy() { super.onDestroy(); if (progressDialog ! null progressDialog.isShowing()) { progressDialog.dismiss(); } } }6. 性能优化与最佳实践6.1 图像和视频缓存策略实现高效的缓存机制来提升用户体验// 文件路径app/src/main/java/com/worldcup/lineup/cache/MediaCache.java public class MediaCache { private static final long MAX_CACHE_SIZE 100 * 1024 * 1024; // 100MB private final LruCacheString, Bitmap memoryCache; private final File cacheDir; public MediaCache(Context context) { // 计算可用的内存缓存大小 int maxMemory (int) (Runtime.getRuntime().maxMemory() / 1024); int cacheSize maxMemory / 8; // 使用1/8的可用内存 memoryCache new LruCacheString, Bitmap(cacheSize) { Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getByteCount() / 1024; } }; cacheDir new File(context.getCacheDir(), media); if (!cacheDir.exists()) { cacheDir.mkdirs(); } } public void putBitmap(String key, Bitmap bitmap) { if (getBitmap(key) null) { memoryCache.put(key, bitmap); } } public Bitmap getBitmap(String key) { return memoryCache.get(key); } public File getVideoFile(String videoUrl) { String filename video_ hashKeyForDisk(videoUrl) .mp4; return new File(cacheDir, filename); } public boolean isVideoCached(String videoUrl) { File videoFile getVideoFile(videoUrl); return videoFile.exists(); } private String hashKeyForDisk(String key) { String cacheKey; try { MessageDigest digest MessageDigest.getInstance