Android简易音乐重构MVVM Java版-新增我喜欢的歌单展示+底部bar点击跳转播放功能(十九)

关于

效果

在这里插入图片描述

修改MainActivity

  新增底部bar初始化

private void initBottomBar() {
        viewModel.getRecentSong().observe(this,recentSongInfoEntityApiResponse -> {
            if (recentSongInfoEntityApiResponse.getStatus() == Status.SUCCESS && recentSongInfoEntityApiResponse.getData().getData().getList().size() >0){
                RecentSongInfoEntity.RecentDataEntity.ListEntity.DataEntity data =recentSongInfoEntityApiResponse.getData().getData().getList()
                        .get(0).getData();
                viewModel.currentSongName.set(data.getName());
                viewModel.currentSongUrl.set(data.getAl().getPicUrl());
                MusicInfo musicInfo = new MusicInfo();
                musicInfo.setArtist(data.getAr().get(0).getName());
                musicInfo.setSongId(data.getId()+"");
                musicInfo.setSongName(data.getName());
                musicInfo.setSongCover(data.getAl().getPicUrl());
                musicInfo.setSongUrl(SONG_URL+data.getId());
                viewModel.currentMusicInfo = musicInfo;
            }
        });

        MusicPlay.onPlayStateListener(this, new OnMusicPlayStateListener() {
            @Override
            public void onPlayState(@NonNull PlayManger playManger) {
                viewModel.currentSongUrl.set(playManger.getSongInfo().getSongCover());
                viewModel.currentSongName.set(playManger.getSongInfo().getSongName());
                switch (playManger.getStage()){
                    case PlayManger.PAUSE:
                    case PlayManger.IDLE:
                        binding.songBar.ivBottomPlay.setImageResource(R.drawable.shape_play);
                        break;
                    case PlayManger.PLAYING:
                        binding.songBar.ivBottomPlay.setImageResource(R.drawable.shape_pause_black);
                        viewModel.currentMusicInfo = playManger.getSongInfo();
                        break;
                    case PlayManger.BUFFERING:
                        ViewExtensionKt.printLog("缓冲");
                        break;
                    case PlayManger.SWITCH:
                        viewModel.currentMusicInfo = playManger.getSongInfo();
                        break;

                }
            }
        });

        binding.songBar.rootBottomBar.setOnClickListener(view -> {
            if (ClickUtil.enableClick()){
                MusicPlay.playMusicByInfo(viewModel.currentMusicInfo);
                startActivity(new Intent(this, CurrentSongPlayActivity.class)
                        .putExtra(MUSIC_INFO, viewModel.currentMusicInfo));
            }
        });
        binding.songBar.ivBottomPlay.setOnClickListener(view -> {
            if (MusicPlay.isPlaying()){
                MusicPlay.pauseMusic();
            }else if (MusicPlay.isPaused()){
                MusicPlay.restoreMusic();
            }else {
                MusicPlay.playMusicByInfo(viewModel.currentMusicInfo);
            }
        });
    }

修改fragment_mine.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="vm"
            type="com.tobery.personalmusic.ui.home.MainViewModel" />
        <variable
            name="my"
            type="com.tobery.personalmusic.ui.home.mine.MineFragmentViewModel" />
    </data>

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/grays_10">


    <View
        android:id="@+id/view_nike"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_0"
        android:layout_marginTop="@dimen/dp_40"
        android:background="@drawable/bg_view_white_full"
        android:paddingBottom="@dimen/dp_24"
        app:layout_constraintTop_toTopOf="@id/img_head"
        app:layout_constraintBottom_toBottomOf="@id/tv_follow"
        android:padding="@dimen/dp_24"
        android:layout_marginStart="@dimen/dp_16"
        android:layout_marginEnd="@dimen/dp_16"
        />

    <ImageView
        android:id="@+id/img_head"
        android:layout_width="@dimen/dp_80"
        android:layout_height="@dimen/dp_80"
        imSrc="@{vm.ui.imageUrl}"
        error="@{@drawable/ic_banner_loading}"
        android:layout_margin="@dimen/dp_16"
        android:elevation="@dimen/dp_8"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <WebView
        android:id="@+id/web_vip"
        android:layout_width="@dimen/dp_40"
        android:layout_height="@dimen/dp_20"
        app:layout_constraintBottom_toBottomOf="@id/tv_nickname"
        app:layout_constraintStart_toEndOf="@id/tv_nickname"
        android:layout_marginStart="@dimen/dp_5"
        />

    <TextView
        android:id="@+id/tv_nickname"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{vm.ui.nickname}"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_18"
        android:textStyle="bold"
        app:layout_constraintTop_toBottomOf="@id/img_head"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginEnd="@dimen/dp_8"
        />

    <TextView
        android:id="@+id/tv_follow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{vm.ui.follows}"
        android:textSize="@dimen/sp_14"
        android:textColor="@color/grays_66"
        android:layout_marginEnd="@dimen/dp_16"
        android:paddingBottom="@dimen/dp_8"
        app:layout_constraintTop_toBottomOf="@id/tv_nickname"
        app:layout_constraintEnd_toStartOf="@id/tv_fans"
        />
    <TextView
        android:id="@+id/tv_fans"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{vm.ui.followeds}"
        android:textSize="@dimen/sp_14"
        android:textColor="@color/grays_66"
        app:layout_constraintTop_toBottomOf="@id/tv_nickname"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        />

    <TextView
        android:id="@+id/tv_level"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{my.level}"
        android:textSize="@dimen/sp_14"
        android:textColor="@color/grays_66"
        android:layout_marginStart="@dimen/dp_16"
        app:layout_constraintTop_toBottomOf="@id/tv_nickname"
        app:layout_constraintStart_toEndOf="@id/tv_fans"
        />

    <View
        android:id="@+id/view_like_item"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_80"
        app:layout_constraintTop_toBottomOf="@id/view_nike"
        android:background="@drawable/bg_view_white_full"
        android:layout_margin="@dimen/dp_16"
        />

    <ImageView
        android:id="@+id/img_cover"
        android:layout_width="@dimen/dp_60"
        android:layout_height="@dimen/dp_60"
        app:layout_constraintTop_toTopOf="@id/view_like_item"
        app:layout_constraintBottom_toBottomOf="@id/view_like_item"
        app:layout_constraintStart_toStartOf="@id/view_like_item"
        android:layout_marginStart="@dimen/dp_16"
        rectangleSrc="@{my.mineLikeCover}"
        />

    <TextView
        android:id="@+id/tv_introduction"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:text="music"
        android:textSize="@dimen/sp_16"
        android:layout_marginStart="@dimen/dp_8"
        app:layout_constraintTop_toTopOf="@id/view_like_item"
        app:layout_constraintBottom_toTopOf="@id/tv_count"
        app:layout_constraintStart_toEndOf="@id/img_cover"
        />

    <TextView
        android:id="@+id/tv_count"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/grays_66"
        android:text="@{my.trackCount}"
        android:textSize="@dimen/sp_12"
        android:layout_marginStart="@dimen/dp_8"
        app:layout_constraintTop_toBottomOf="@id/tv_introduction"
        app:layout_constraintBottom_toBottomOf="@id/view_like_item"
        app:layout_constraintStart_toEndOf="@id/img_cover"
        />



</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

修改MainViewModel

public class MainViewModel extends ViewModel {

    private SavedStateHandle state;

    public UserInfoUi ui;

    private String userInfo;

    public ObservableField<String> currentSongUrl = new ObservableField<>("");
    public ObservableField<String> currentSongName = new ObservableField<>("");
    public MusicInfo currentMusicInfo;

    public MainViewModel(SavedStateHandle savedStateHandle) {
        this.state = savedStateHandle;
        ui = state.get(KEY_MAIN_UI) == null ? new UserInfoUi(new ObservableField<>(""), new ObservableField<>(""), new ObservableInt(0), new ObservableField<>(""), new ObservableField<>(""), new ObservableField<>(""), new ObservableField<>("")) : state.get(KEY_MAIN_UI);
    }

    public void initUi() {
        userInfo = SharePreferencesUtil.getInstance(ContextProvider.get().getContext())
                .getUserInfo();
        LoginEntity data = new Gson().fromJson(userInfo, LoginEntity.class);
        if (null != data.getProfile()) {
            ui.nickname.set(data.getProfile().getNickname());
            ui.imageUrl.set(data.getProfile().getAvatarUrl());
            ui.userId.set(data.getProfile().getUserId());
            ui.signature.set(data.getProfile().getSignature());
            ui.follows.set(data.getProfile().getFollows()+"关注");
            ui.followeds.set(data.getProfile().getFolloweds()+"粉丝");
        }
    }

    public LiveData<ApiResponse<UserDetailEntity>> getUserDetails() {
        return RetrofitUtils.getmApiUrl().getUserDetails(ui.userId.get());
    }

    public LiveData<ApiResponse<RecentSongInfoEntity>> getRecentSong(){
        return RetrofitUtils.getmApiUrl().getRecentSong(1);
    }


}

添加用户profile

public class UserInfoUi implements Serializable {

    public ObservableField<String> imageUrl;
    public ObservableField<String> nickname;//昵称
    public ObservableInt userId;
    public ObservableField<String> signature;//个签
    public ObservableField<String> follows;//关注
    public ObservableField<String> followeds;//粉丝
    public ObservableField<String> level;//用户等级

    public UserInfoUi(ObservableField<String> imageUrl, ObservableField<String> nickname, ObservableInt userId,ObservableField<String> signature, ObservableField<String> follows, ObservableField<String> followeds,ObservableField<String> level) {
        this.nickname = nickname;
        this.imageUrl = imageUrl;
        this.userId = userId;
        this.signature = signature;
        this.follows = follows;
        this.followeds = followeds;
        this.level = level;
    }
}

添加用户信息接口

@GET("user/detail")//用户信息
    LiveData<ApiResponse<UserDetailEntity>> getUserDetails(@Query("uid") long userId);
@GET("user/playlist") //用户歌单
    LiveData<ApiResponse<UserPlayEntity>> getUserPlayList(@Query("uid") long userId);

添加用户实体类UserDetailEntity

@NoArgsConstructor
@Data
public class UserDetailEntity {

    private int level;
    private int listenSongs;
    private UserPointEntity userPoint;
    private boolean mobileSign;
    private boolean pcSign;
    private ProfileEntity profile;
    private boolean peopleCanSeeMyPlayRecord;
    private List<BindingsEntity> bindings;
    private boolean adValid;
    private int code;
    private long createTime;
    private int createDays;
    private ProfileVillageInfoEntity profileVillageInfo;

    @NoArgsConstructor
    @Data
    public static class UserPointEntity {
        private int userId;
        private int balance;
        private long updateTime;
        private int version;
        private int status;
        private int blockBalance;
    }

    @NoArgsConstructor
    @Data
    public static class ProfileEntity {
        private PrivacyItemUnlimitEntity privacyItemUnlimit;
        private Object avatarDetail;
        private String backgroundImgIdStr;
        private String avatarImgIdStr;
        private String description;
        private int userId;
        private int vipType;
        private int userType;
        private long createTime;
        private String nickname;
        private String avatarUrl;
        private int gender;
        private boolean mutual;
        private boolean followed;
        private Object remarkName;
        private int authStatus;
        private String detailDescription;
        private ExpertsEntity experts;
        private Object expertTags;
        private int djStatus;
        private int accountStatus;
        private int province;
        private int city;
        private boolean defaultAvatar;
        private long backgroundImgId;
        private String backgroundUrl;
        private long birthday;
        private long avatarImgId;
        private String signature;
        private int authority;
        private int followeds;
        private int follows;
        private boolean blacklist;
        private int eventCount;
        private int allSubscribedCount;
        private int playlistBeSubscribedCount;
        private String avatarImgId_str;
        private Object followTime;
        private boolean followMe;
        private List<?> artistIdentity;
        private int cCount;
        private boolean inBlacklist;
        private int sDJPCount;
        private int playlistCount;
        private int sCount;
        private int newFollows;

        @NoArgsConstructor
        @Data
        public static class PrivacyItemUnlimitEntity {
            private boolean area;
            private boolean college;
            private boolean age;
            private boolean villageAge;
        }

        @NoArgsConstructor
        @Data
        public static class ExpertsEntity {
        }
    }

    @NoArgsConstructor
    @Data
    public static class ProfileVillageInfoEntity {
        private String title;
        private Object imageUrl;
        private String targetUrl;
    }

    @NoArgsConstructor
    @Data
    public static class BindingsEntity {
        private boolean expired;
        private String url;
        private int userId;
        private int expiresIn;
        private int refreshTime;
        private long bindingTime;
        private Object tokenJsonStr;
        private long id;
        private int type;
    }
}

修改MineFragmentViewModel

public class MineFragmentViewModel extends ViewModel {

    public ObservableField<String> mineLikeCover = new ObservableField<>("");
    public ObservableField<String> trackCount = new ObservableField<>("");
    public ObservableField<String> level = new ObservableField<>("");
    public Long userLikeCreator = 0L;

    public LiveData<ApiResponse<VipInfoEntity>> getVipInfo(){
        return RetrofitUtils.getmApiUrl().getVipInfo();
    }
    //获取用户歌单
    public LiveData<ApiResponse<UserPlayEntity>> getUserPlayList(Long userId){
        return RetrofitUtils.getmApiUrl().getUserPlayList(userId);
    }

}

添加用户歌单实体类UserPlayEntity

@NoArgsConstructor
@Data
public class UserPlayEntity {

    private String version;
    private boolean more;
    private List<PlaylistEntity> playlist;
    private int code;

    @NoArgsConstructor
    @Data
    public static class PlaylistEntity {
        private List<?> subscribers;
        private boolean subscribed;
        private CreatorEntity creator;
        private Object artists;
        private Object tracks;
        private Object updateFrequency;
        private long backgroundCoverId;
        private Object backgroundCoverUrl;
        private long titleImage;
        private Object titleImageUrl;
        private Object englishTitle;
        private boolean opRecommend;
        private Object recommendInfo;
        private int subscribedCount;
        private int cloudTrackCount;
        private int userId;
        private int totalDuration;
        private long coverImgId;
        private int privacy;
        private long trackUpdateTime;
        private int trackCount;
        private long updateTime;
        private String commentThreadId;
        private String coverImgUrl;
        private int specialType;
        private boolean anonimous;
        private long createTime;
        private boolean highQuality;
        private boolean newImported;
        private long trackNumberUpdateTime;
        private long playCount;
        private int adType;
        private Object description;
        private List<?> tags;
        private boolean ordered;
        private int status;
        private String name;
        private long id;
        private String coverImgId_str;
        private Object sharedUsers;
        private Object shareStatus;

        @NoArgsConstructor
        @Data
        public static class CreatorEntity {
            private boolean defaultAvatar;
            private int province;
            private int authStatus;
            private boolean followed;
            private String avatarUrl;
            private int accountStatus;
            private int gender;
            private int city;
            private int birthday;
            private int userId;
            private int userType;
            private String nickname;
            private String signature;
            private String description;
            private String detailDescription;
            private long avatarImgId;
            private long backgroundImgId;
            private String backgroundUrl;
            private int authority;
            private boolean mutual;
            private Object expertTags;
            private Object experts;
            private int djStatus;
            private int vipType;
            private Object remarkName;
            private int authenticationTypes;
            private Object avatarDetail;
            private boolean anchor;
            private String avatarImgIdStr;
            private String backgroundImgIdStr;
            private String avatarImgId_str;
        }
    }
}

修改MineFragment

public class MineFragment extends Fragment {

    private FragmentMineBinding binding;

    private MainViewModel homeViewModel;

    private MineFragmentViewModel viewModel;


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = FragmentMineBinding.inflate(inflater,container,false);
        homeViewModel = new ViewModelProvider(this).get(MainViewModel.class);
        viewModel = new ViewModelProvider(this).get(MineFragmentViewModel.class);
        binding.setLifecycleOwner(this);
        binding.setVm(homeViewModel);
        binding.setMy(viewModel);
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        homeViewModel.initUi();
        initWebView();
        initView();
        initObserver();
    }

    private void initView() {
        binding.viewLikeItem.setOnClickListener(v -> {
            if (ClickUtil.enableClick()){
               startActivity(new Intent(getActivity(), MinePlayListActivity.class)
                        .putExtra(PLAYLIST_ID,viewModel.userLikeCreator)
                        .putExtra(PLAY_NAME,"歌单"));
            }
        });
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void initWebView() {
        binding.webVip.getSettings().setJavaScriptEnabled(true);
    }

    private void initObserver() {

        viewModel.getVipInfo().observe(getViewLifecycleOwner(), vipInfoEntityApiResponse -> {
            if (vipInfoEntityApiResponse.getStatus() == Status.SUCCESS && vipInfoEntityApiResponse.getData().getData().getRedVipDynamicIconUrl2()!= null){
                binding.webVip.loadDataWithBaseURL(null,changeImageUrl(vipInfoEntityApiResponse.getData().getData().getRedVipDynamicIconUrl2()),"text/html", "utf-8", null);
            }
        });

        homeViewModel.getUserDetails().observe(getViewLifecycleOwner(), userDetailEntityApiResponse -> {
            if (userDetailEntityApiResponse.getStatus() == Status.SUCCESS){
                viewModel.level.set("Lv."+userDetailEntityApiResponse.getData().getLevel());
            }
        });

        viewModel.getUserPlayList(Long.valueOf(homeViewModel.ui.userId.get())).observe(getViewLifecycleOwner(), userPlayEntityApiResponse -> {
            ViewExtensionKt.printLog(userPlayEntityApiResponse.getMessage());
            if (userPlayEntityApiResponse.getStatus() == Status.SUCCESS){
                UserPlayEntity.PlaylistEntity userLike = userPlayEntityApiResponse.getData().getPlaylist().get(0);
                viewModel.mineLikeCover.set(userLike.getCoverImgUrl());
                viewModel.trackCount.set(userLike.getTrackCount()+"");
                viewModel.userLikeCreator = userLike.getId();
            }
        });
    }

    private String changeImageUrl(String url) {
        Document doc = null;
        try {
            InputStream file = getResources().getAssets().open("web/vip.html");
            doc = Jsoup.parse(file, "UTF-8", url);
            Elements pngs = doc.select("img[src$=.png]");
            pngs.attr("src",url);
            file.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        assert doc != null;
        return doc.toString();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪の星空朝酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值