Skip to content

Commit 608a72a

Browse files
Merge pull request #56 from MihaiCristianCondrea/codex/create-homeuistate-data-class
Refactor home screen state management
2 parents 189e26d + d3985cb commit 608a72a

File tree

3 files changed

+67
-63
lines changed

3 files changed

+67
-63
lines changed

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/home/HomeFragment.java

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,27 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
3232
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
3333
super.onViewCreated(view, savedInstanceState);
3434
homeViewModel = new ViewModelProvider(this).get(HomeViewModel.class);
35-
homeViewModel.getAnnouncementTitle().observe(getViewLifecycleOwner(), title -> binding.announcementTitle.setText(title));
36-
homeViewModel.getAnnouncementSubtitle().observe(getViewLifecycleOwner(), subtitle -> binding.announcementSubtitle.setText(subtitle));
37-
homeViewModel.getDailyTip().observe(getViewLifecycleOwner(), tip -> {
38-
binding.tipText.setText(tip);
39-
binding.shareTipButton.setOnClickListener(v -> shareTip(tip));
35+
LayoutInflater inflater = LayoutInflater.from(requireContext());
36+
homeViewModel.getUiState().observe(getViewLifecycleOwner(), state -> {
37+
binding.announcementTitle.setText(state.announcementTitle());
38+
binding.announcementSubtitle.setText(state.announcementSubtitle());
39+
binding.tipText.setText(state.dailyTip());
40+
binding.shareTipButton.setOnClickListener(v -> shareTip(state.dailyTip()));
41+
42+
ViewGroup promotedContainer = binding.promotedAppsContainer;
43+
binding.scrollView.clearFocus();
44+
promotedContainer.clearFocus();
45+
promotedContainer.removeAllViews();
46+
for (com.d4rk.androidtutorials.java.data.model.PromotedApp app : state.promotedApps()) {
47+
com.d4rk.androidtutorials.java.databinding.PromotedAppItemBinding itemBinding =
48+
com.d4rk.androidtutorials.java.databinding.PromotedAppItemBinding.inflate(inflater, promotedContainer, false);
49+
loadImage(app.iconUrl(), itemBinding.appIcon);
50+
itemBinding.appName.setText(app.name());
51+
itemBinding.appDescription.setVisibility(android.view.View.GONE);
52+
itemBinding.appButton.setOnClickListener(v -> startActivity(homeViewModel.getPromotedAppIntent(app.packageName())));
53+
promotedContainer.addView(itemBinding.getRoot());
54+
}
4055
});
41-
setupPromotions(LayoutInflater.from(requireContext()));
4256
new FastScrollerBuilder(binding.scrollView)
4357
.useMd2Style()
4458
.build();
@@ -67,24 +81,6 @@ private void shareTip(String tip) {
6781
startActivity(android.content.Intent.createChooser(shareIntent, getString(com.d4rk.androidtutorials.java.R.string.share_using)));
6882
}
6983

70-
private void setupPromotions(LayoutInflater inflater) {
71-
ViewGroup container = binding.promotedAppsContainer;
72-
homeViewModel.getPromotedApps().observe(getViewLifecycleOwner(), apps -> {
73-
binding.scrollView.clearFocus();
74-
container.clearFocus();
75-
container.removeAllViews();
76-
for (com.d4rk.androidtutorials.java.data.model.PromotedApp app : apps) {
77-
com.d4rk.androidtutorials.java.databinding.PromotedAppItemBinding itemBinding =
78-
com.d4rk.androidtutorials.java.databinding.PromotedAppItemBinding.inflate(inflater, container, false);
79-
loadImage(app.iconUrl(), itemBinding.appIcon);
80-
itemBinding.appName.setText(app.name());
81-
itemBinding.appDescription.setVisibility(android.view.View.GONE);
82-
itemBinding.appButton.setOnClickListener(v -> startActivity(homeViewModel.getPromotedAppIntent(app.packageName())));
83-
container.addView(itemBinding.getRoot());
84-
}
85-
});
86-
}
87-
8884
private void loadImage(String url, android.widget.ImageView imageView) {
8985
com.android.volley.toolbox.ImageRequest request = new com.android.volley.toolbox.ImageRequest(
9086
url,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.d4rk.androidtutorials.java.ui.screens.home;
2+
3+
import java.util.List;
4+
5+
import com.d4rk.androidtutorials.java.data.model.PromotedApp;
6+
7+
/**
8+
* Represents the UI state for the Home screen.
9+
*/
10+
public record HomeUiState(
11+
String announcementTitle,
12+
String announcementSubtitle,
13+
String dailyTip,
14+
List<PromotedApp> promotedApps
15+
) {}
16+

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/home/HomeViewModel.java

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
import android.content.Intent;
55
import android.net.Uri;
66

7-
import androidx.lifecycle.ViewModel;
87
import androidx.lifecycle.LiveData;
98
import androidx.lifecycle.MutableLiveData;
9+
import androidx.lifecycle.ViewModel;
1010

1111
import com.d4rk.androidtutorials.java.R;
1212
import com.d4rk.androidtutorials.java.data.model.PromotedApp;
@@ -29,10 +29,7 @@ public class HomeViewModel extends ViewModel {
2929
private final GetDailyTipUseCase getDailyTipUseCase;
3030
private final GetPromotedAppsUseCase getPromotedAppsUseCase;
3131

32-
private final MutableLiveData<String> announcementTitle = new MutableLiveData<>();
33-
private final MutableLiveData<String> announcementSubtitle = new MutableLiveData<>();
34-
private final MutableLiveData<String> dailyTip = new MutableLiveData<>();
35-
private final MutableLiveData<List<PromotedApp>> promotedApps = new MutableLiveData<>(new ArrayList<>());
32+
private final MutableLiveData<HomeUiState> uiState = new MutableLiveData<>();
3633

3734
@Inject
3835
public HomeViewModel(Application application,
@@ -44,43 +41,45 @@ public HomeViewModel(Application application,
4441
this.getDailyTipUseCase = getDailyTipUseCase;
4542
this.getPromotedAppsUseCase = getPromotedAppsUseCase;
4643

47-
announcementTitle.setValue(application.getString(R.string.announcement_title));
48-
announcementSubtitle.setValue(application.getString(R.string.announcement_subtitle));
49-
dailyTip.setValue(getDailyTipUseCase.invoke());
44+
HomeUiState initialState = new HomeUiState(
45+
application.getString(R.string.announcement_title),
46+
application.getString(R.string.announcement_subtitle),
47+
getDailyTipUseCase.invoke(),
48+
new ArrayList<>()
49+
);
50+
uiState.setValue(initialState);
5051

5152
getPromotedAppsUseCase.invoke(apps -> {
53+
List<PromotedApp> result;
5254
if (apps.isEmpty()) {
53-
promotedApps.postValue(apps);
54-
return;
55+
result = apps;
56+
} else {
57+
int startIndex = (int) ((System.currentTimeMillis() / (24L * 60 * 60 * 1000)) % apps.size());
58+
result = new ArrayList<>();
59+
for (int i = 0; i < Math.min(4, apps.size()); i++) {
60+
result.add(apps.get((startIndex + i) % apps.size()));
61+
}
5562
}
56-
int startIndex = (int) ((System.currentTimeMillis() / (24L * 60 * 60 * 1000)) % apps.size());
57-
List<PromotedApp> rotated = new ArrayList<>();
58-
for (int i = 0; i < Math.min(4, apps.size()); i++) {
59-
rotated.add(apps.get((startIndex + i) % apps.size()));
63+
HomeUiState current = uiState.getValue();
64+
if (current == null) {
65+
current = new HomeUiState("", "", "", result);
66+
} else {
67+
current = new HomeUiState(
68+
current.announcementTitle(),
69+
current.announcementSubtitle(),
70+
current.dailyTip(),
71+
result
72+
);
6073
}
61-
promotedApps.postValue(rotated);
74+
uiState.postValue(current);
6275
});
6376
}
6477

6578
/**
66-
* Provides a LiveData for the announcement title.
67-
*/
68-
public LiveData<String> getAnnouncementTitle() {
69-
return announcementTitle;
70-
}
71-
72-
/**
73-
* Provides a LiveData for the announcement subtitle.
74-
*/
75-
public LiveData<String> getAnnouncementSubtitle() {
76-
return announcementSubtitle;
77-
}
78-
79-
/**
80-
* Provides a LiveData for the tip of the day text.
79+
* Exposes the UI state for the Home screen.
8180
*/
82-
public LiveData<String> getDailyTip() {
83-
return dailyTip;
81+
public LiveData<HomeUiState> getUiState() {
82+
return uiState;
8483
}
8584

8685
/**
@@ -91,13 +90,6 @@ public Intent getOpenPlayStoreIntent() {
9190
return buildPlayStoreIntent(homeRepository.getPlayStoreUrl());
9291
}
9392

94-
/**
95-
* List of apps to promote on the Home screen.
96-
*/
97-
public LiveData<List<PromotedApp>> getPromotedApps() {
98-
return promotedApps;
99-
}
100-
10193
/**
10294
* Builds an intent to open the Google Play listing for the provided package.
10395
*/

0 commit comments

Comments
 (0)