diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index b268ef3..55829cb 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -4,6 +4,14 @@ diff --git a/app/src/main/java/com/example/tampopo_client/viewmodels/ActivityViewModel.java b/app/src/main/java/com/example/tampopo_client/viewmodels/ActivityViewModel.java index 0c74253..3cc9160 100644 --- a/app/src/main/java/com/example/tampopo_client/viewmodels/ActivityViewModel.java +++ b/app/src/main/java/com/example/tampopo_client/viewmodels/ActivityViewModel.java @@ -17,8 +17,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; +import java.util.stream.Collectors; import retrofit2.Call; import retrofit2.Callback; @@ -26,20 +28,14 @@ import retrofit2.Retrofit; import retrofit2.converter.jackson.JacksonConverterFactory; -/** - * アクティビティを扱うためのViewModel - * - * @author Shohei Yamagiwa - * @implNote Repositoryは作成せずに、すべてViewModelで処理する - */ public class ActivityViewModel extends RealTimeViewModel { private final ActivitiesResource activitiesResource; private final UserResource userResource; - private final MutableLiveData myLatestActivityLiveData; // 自分の最新のアクティビティ - private final Map>> friendToActivitiesLiveData; // <フレンドのユーザーID, フレンドのアクティビティのリスト> - private final MutableLiveData> friendUserIdsLiveData; // フレンドのユーザーIDのリスト - private final MutableLiveData> allFriendsLatestActivitiesLiveData; // 全フレンドの最新アクティビティのリスト + private final MutableLiveData myLatestActivityLiveData; + private final Map>> friendToActivitiesLiveData; + private final MutableLiveData> friendUserIdsLiveData; + private final MutableLiveData> allFriendsLatestActivitiesLiveData; private final String myUserId; private final String myToken; @@ -48,17 +44,10 @@ private final List sortedFriendUserIds = new ArrayList<>(); - /** - * ActivityのViewModelを作成する。 - * - * @param myUserId 自身のユーザーID - * @param myToken 自身の認証用トークン - */ public ActivityViewModel(String myUserId, String myToken) { this.myUserId = myUserId; this.myToken = myToken; - // Retrofitの初期化 final Retrofit retrofit = new Retrofit.Builder().baseUrl("http://nitta-lab-www.is.konan-u.ac.jp/tampopo/").addConverterFactory(JacksonConverterFactory.create()).build(); activitiesResource = retrofit.create(ActivitiesResource.class); userResource = retrofit.create(UserResource.class); @@ -66,7 +55,7 @@ friendToActivitiesLiveData = new HashMap<>(); friendUserIdsLiveData = new MutableLiveData<>(List.of()); myLatestActivityLiveData = new MutableLiveData<>(null); - allFriendsLatestActivitiesLiveData = new MutableLiveData<>(new ArrayList<>()); // 初期化 + allFriendsLatestActivitiesLiveData = new MutableLiveData<>(new ArrayList<>()); userActivityStatusChangeListeners = new ArrayList<>(); } @@ -78,28 +67,9 @@ return; } - // 自分の最新のアクティビティを取得する pullLatestActivity(myUserId, activitiesResource, new ActivityFetchCallback() { @Override public void onSuccess(Activity activity) { - Activity prevActivity = myLatestActivityLiveData.getValue(); - - // アクティビティが更新されていない場合 - LocalDateTime now = LocalDateTime.now(); - LocalDateTime lastUpdatedTime = getDateTimeFromString(activity.getUpdateTime()); - - if (now.isAfter(lastUpdatedTime.plusSeconds(5))) { - for (UserActivityStatusChangeListener observer : userActivityStatusChangeListeners) { - // アクティビティのステータス変更をリスナーに通知する - if (activity.equals(prevActivity)) { - observer.onUserStatusChanged(myUserId, UserActivityStatusChangeListener.Status.INACTIVE); - } else { - observer.onUserStatusChanged(myUserId, UserActivityStatusChangeListener.Status.ACTIVE); - } - } - } - - // 自分の新しいアクティビティをLiveDataに反映する myLatestActivityLiveData.postValue(activity); } @@ -109,15 +79,20 @@ } }); - // 自分のフレンドの最新のアクティビティを取得して更新する - if (friendUserIdsLiveData.isInitialized() && friendUserIdsLiveData.getValue() != null) { - List latestActivities = new ArrayList<>(); + if (friendUserIdsLiveData.getValue() != null) { for (String userId : friendUserIdsLiveData.getValue()) { pullLatestActivity(userId, activitiesResource, new ActivityFetchCallback() { @Override public void onSuccess(Activity activity) { - updateFriendToActivitiesLiveData(activity, userId); - latestActivities.add(activity); + List currentActivities = allFriendsLatestActivitiesLiveData.getValue(); + if (currentActivities == null) { + currentActivities = new ArrayList<>(); + } + // 既存のリストから同じユーザーIDのアクティビティを削除 + currentActivities.removeIf(a -> a.getUserId().equals(activity.getUserId())); + // 新しいアクティビティを追加 + currentActivities.add(activity); + allFriendsLatestActivitiesLiveData.postValue(currentActivities); } @Override @@ -126,50 +101,21 @@ } }); } - allFriendsLatestActivitiesLiveData.postValue(latestActivities); } - if (friendUserIdsLiveData.isInitialized()) { - // 最新のフレンドのユーザーIDを取得して更新する - // TODO: 適切なコールバックを使う必要あり - pullLatestFriendUserIds(myUserId, myToken); - } + pullLatestFriendUserIds(myUserId, myToken); }; } - /** - * ユーザIDからそのユーザーのアクティビティのリストのライブデータを取得し、最新のアクティビティに更新する - * - * @param latestActivity 最新のアクティビティ - * @param userId 更新対象のユーザーID - */ private void updateFriendToActivitiesLiveData(Activity latestActivity, String userId) { - if (friendToActivitiesLiveData.get(userId) == null) { - friendToActivitiesLiveData.put(userId, new MutableLiveData<>(List.of())); - } - MutableLiveData> userActivitiesLiveData = friendToActivitiesLiveData.get(userId); - assert userActivitiesLiveData != null; - + MutableLiveData> userActivitiesLiveData = friendToActivitiesLiveData.computeIfAbsent(userId, k -> new MutableLiveData<>(new ArrayList<>())); List userActivities = userActivitiesLiveData.getValue(); - if (userActivities == null || userActivities.isEmpty()) { - userActivitiesLiveData.postValue(List.of(latestActivity)); - } else { - if (userActivities.equals(List.of(latestActivity))) { - return; - } - + if (userActivities == null || userActivities.isEmpty() || !userActivities.get(0).equals(latestActivity)) { userActivitiesLiveData.postValue(List.of(latestActivity)); } } - /** - * 自身のアクティビティを新しく作成する - * - * @param userId 自身のユーザーID - * @param token 自身の認証用トークン - * @param newActivity 新しいアクティビティのテキスト - */ public void createActivity(String userId, String token, String newActivity) { if (!myLatestActivityLiveData.isInitialized()) { return; @@ -181,16 +127,16 @@ public void onResponse(@NonNull Call call, @NonNull Response response) { if (response.isSuccessful()) { String createdActivityId = response.body(); + if (createdActivityId == null) return; Call getActivityCall = activitiesResource.getActivity(userId, createdActivityId); getActivityCall.enqueue(new Callback() { @Override public void onResponse(@NonNull Call call, @NonNull Response response) { Activity createdActivity = response.body(); - if (createdActivity == null) { - return; + if (createdActivity != null) { + myLatestActivityLiveData.postValue(createdActivity); } - myLatestActivityLiveData.postValue(createdActivity); } @Override @@ -210,83 +156,40 @@ }); } - /** - * 最新のユーザーのアクティビティを取得・更新する - * - * @param userId 取得対象のユーザーのID - * @param resource アクティビティのリソース - * @param callback アクティビティが取得された後に呼び出されるコールバック - */ private void pullLatestActivity(String userId, ActivitiesResource resource, ActivityFetchCallback callback) { Call> fetchActivityCall = resource.getActivities(userId, "LATEST"); fetchActivityCall.enqueue(new Callback>() { @Override public void onResponse(@NonNull Call> call, @NonNull Response> response) { - if (response.isSuccessful()) { - Collection activities = response.body().values(); // アクティビティが存在しない場合は空のリスト - if (activities == null || activities.isEmpty()) { - return; + if (response.isSuccessful() && response.body() != null) { + Collection activities = response.body().values(); + if (!activities.isEmpty()) { + callback.onSuccess(activities.iterator().next()); } - - Activity latestActivity = activities.iterator().next(); - callback.onSuccess(latestActivity); } } @Override public void onFailure(@NonNull Call> call, @NonNull Throwable t) { Log.e(ActivityViewModel.class.getSimpleName(), "An error has occurred while fetching the latest activity.", t); - callback.onFailure(t); } }); } - /** - * String型の日時をLocalDateTime型に変換する - * - * @param dateTime 変換対象の日時(文字列) - * @return 変換後の日時(LocalDateTime) - */ private static LocalDateTime getDateTimeFromString(String dateTime) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); return LocalDateTime.parse(dateTime, formatter); } - /** - * 最新の自分のフレンドのユーザーIDをすべて取得・更新する。 - * - * @param userId 自分のユーザーID - * @param token 自分のユーザー認証用トークン - */ private void pullLatestFriendUserIds(String userId, String token) { Call> fetchFriendUserIdsCall = userResource.getFriends(userId, token); fetchFriendUserIdsCall.enqueue(new Callback>() { @Override public void onResponse(@NonNull Call> call, @NonNull Response> response) { - if (response.isSuccessful()) { - - // MEMO: 入れ込んだだけ - // フレンドのIDをアクティビティ更新順に並べ替える - List friendUserIds = friendUserIdsLiveData.getValue(); - if (friendUserIds == null || !friendUserIds.equals(response.body())) { + if (response.isSuccessful() && response.body() != null) { + if (!Objects.equals(friendUserIdsLiveData.getValue(), response.body())) { friendUserIdsLiveData.postValue(response.body()); - SortedSet friends = new TreeSet<>(new Friend.UpdateTimeComparator()); - - assert friendUserIds != null; - friendUserIds.forEach(userId -> { - List activities = getActivitiesLiveDataFromUserId(userId).getValue(); - if (activities == null || activities.isEmpty()) { - return; - } - - Activity latestActivity = activities.get(0); - friends.add(new Friend(userId, latestActivity.getUpdateTime())); - }); - - // 並び替えたフレンドのユーザーIDを順番に格納して更新する - sortedFriendUserIds.clear(); - friends.forEach(friend -> sortedFriendUserIds.add(friend.getUserId())); } } } @@ -302,17 +205,8 @@ return myLatestActivityLiveData; } - /** - * ユーザIDからそのユーザーのアクティビティのリストのライブデータを取得する - * - * @param userId 取得対象のユーザーID - * @return 取得対象のユーザーのアクティビティのリストのライブデータ - */ public MutableLiveData> getActivitiesLiveDataFromUserId(String userId) { - if (!friendToActivitiesLiveData.containsKey(userId)) { - friendToActivitiesLiveData.put(userId, new MutableLiveData<>()); - } - return friendToActivitiesLiveData.get(userId); + return friendToActivitiesLiveData.computeIfAbsent(userId, k -> new MutableLiveData<>()); } public MutableLiveData> getFriendUserIdsLiveData() { diff --git a/app/src/main/java/com/example/tampopo_client/views/MainActivity.java b/app/src/main/java/com/example/tampopo_client/views/MainActivity.java index baa2bf0..3a854e6 100644 --- a/app/src/main/java/com/example/tampopo_client/views/MainActivity.java +++ b/app/src/main/java/com/example/tampopo_client/views/MainActivity.java @@ -127,7 +127,7 @@ //追加しました!!!!!!!!!!! // ChatViewModelを初期化する - ChatViewModelFactory factory1 = new ChatViewModelFactory(tampopo.getUserId(), tampopo.getToken()); + ChatViewModelFactory factory1 = new ChatViewModelFactory(tampopo.getUserId(), tampopo.getToken(), tampopo.getChatroomId()); chatViewModel = new ViewModelProvider(this, factory1).get(ChatViewModel.class); activityViewModel.getAllFriendsLatestActivitiesLiveData().observe(this, new Observer>() {