com.andryr.musicplayer.activities.SearchActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.andryr.musicplayer.activities.SearchActivity.java

Source

/*
 * Copyright 2016 andryr
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.andryr.musicplayer.activities;

import android.content.Intent;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.SearchView.OnCloseListener;
import android.support.v7.widget.SearchView.OnQueryTextListener;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

import com.andryr.musicplayer.MainActivity;
import com.andryr.musicplayer.R;
import com.andryr.musicplayer.fragments.dialog.AlbumEditorDialog;
import com.andryr.musicplayer.fragments.dialog.ID3TagEditorDialog;
import com.andryr.musicplayer.fragments.dialog.PlaylistPicker;
import com.andryr.musicplayer.images.ArtistImageCache;
import com.andryr.musicplayer.images.ArtworkCache;
import com.andryr.musicplayer.loaders.AlbumLoader;
import com.andryr.musicplayer.loaders.ArtistLoader;
import com.andryr.musicplayer.loaders.BaseLoader;
import com.andryr.musicplayer.loaders.SongLoader;
import com.andryr.musicplayer.model.Album;
import com.andryr.musicplayer.model.Artist;
import com.andryr.musicplayer.model.Playlist;
import com.andryr.musicplayer.model.Song;
import com.andryr.musicplayer.utils.Playlists;
import com.andryr.musicplayer.utils.ThemeHelper;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

//TODO lot of refactoring...
public class SearchActivity extends BaseActivity {

    public static final String FILTER = "filter";
    private static final String TAG = SearchActivity.class.getCanonicalName();

    private boolean mAlbumListLoaded = false;
    private boolean mArtistListLoaded = false;
    private boolean mSongListLoaded = false;
    private View mEmptyView;
    private SearchAdapter mAdapter;
    private int mThumbSize;
    private LoaderManager.LoaderCallbacks<List<Album>> mAlbumLoaderCallbacks = new LoaderManager.LoaderCallbacks<List<Album>>() {

        @Override
        public Loader<List<Album>> onCreateLoader(int id, Bundle args) {

            AlbumLoader loader = new AlbumLoader(SearchActivity.this, null);
            setLoaderFilter(args, loader);

            return loader;
        }

        @Override
        public void onLoadFinished(Loader<List<Album>> loader, List<Album> data) {
            mAlbumListLoaded = true;
            mAdapter.setAlbumList(data);

        }

        @Override
        public void onLoaderReset(Loader<List<Album>> loader) {

        }

    };

    private LoaderManager.LoaderCallbacks<List<Artist>> mArtistLoaderCallbacks = new LoaderManager.LoaderCallbacks<List<Artist>>() {

        @Override
        public void onLoadFinished(Loader<List<Artist>> loader, List<Artist> data) {
            mArtistListLoaded = true;
            mAdapter.setArtistList(data);

        }

        @Override
        public void onLoaderReset(Loader<List<Artist>> loader) {

        }

        @Override
        public Loader<List<Artist>> onCreateLoader(int id, Bundle args) {

            ArtistLoader loader = new ArtistLoader(SearchActivity.this);
            setLoaderFilter(args, loader);
            return loader;
        }
    };
    private LoaderManager.LoaderCallbacks<List<Song>> mSongLoaderCallbacks = new LoaderManager.LoaderCallbacks<List<Song>>() {
        @Override
        public void onLoaderReset(Loader<List<Song>> loader) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onLoadFinished(Loader<List<Song>> loader, List<Song> songList) {
            mSongListLoaded = true;
            mAdapter.setSongList(songList);
            Log.e("test", "" + mAdapter.getItemCount());
        }

        @Override
        public Loader<List<Song>> onCreateLoader(int id, Bundle args) {
            SongLoader loader = new SongLoader(SearchActivity.this);
            setLoaderFilter(args, loader);
            return loader;
        }
    };
    private RecyclerView mRecyclerView;
    private RecyclerView.AdapterDataObserver mEmptyObserver = new RecyclerView.AdapterDataObserver() {

        @Override
        public void onChanged() {
            if (mAdapter.getItemCount() == 0) {
                mEmptyView.setVisibility(View.VISIBLE);
                mRecyclerView.setVisibility(View.GONE);
            } else {
                mEmptyView.setVisibility(View.GONE);
                mRecyclerView.setVisibility(View.VISIBLE);
            }

        }
    };
    private AlbumEditorDialog.OnEditionSuccessListener mOnEditionSuccessListener = new AlbumEditorDialog.OnEditionSuccessListener() {
        @Override
        public void onEditionSuccess() {
            returnToMain(MainActivity.ACTION_REFRESH);
        }
    };

    private static void setLoaderFilter(Bundle args, BaseLoader loader) {
        String filter;
        if (args != null) {
            filter = args.getString(FILTER);
        } else {
            filter = "";
        }
        Log.d(TAG, "filter \"" + filter + "\" " + filter.equals(""));
        loader.setFilter(filter);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);

        mThumbSize = getResources().getDimensionPixelSize(R.dimen.art_thumbnail_size);
        mEmptyView = findViewById(R.id.empty_view);

        mRecyclerView = (RecyclerView) findViewById(R.id.list_view);
        mAdapter = new SearchAdapter();
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        mRecyclerView.setAdapter(mAdapter);

        mAdapter.registerAdapterDataObserver(mEmptyObserver);

        getSupportLoaderManager().initLoader(0, null, mAlbumLoaderCallbacks);
        getSupportLoaderManager().initLoader(1, null, mArtistLoaderCallbacks);
        getSupportLoaderManager().initLoader(2, null, mSongLoaderCallbacks);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.search, menu);
        SearchView search = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));

        search.setOnQueryTextListener(new OnQueryTextListener() {

            @Override
            public boolean onQueryTextSubmit(String query) {
                // TODO Auto-generated method stub
                return true;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                refresh(newText);

                return true;
            }

        });
        search.setOnCloseListener(new OnCloseListener() {

            @Override
            public boolean onClose() {
                refresh();
                return false;
            }
        });
        return true;
    }

    private void refresh(String newText) {
        Bundle args = null;
        if (newText != null) {
            args = new Bundle();
            args.putString(FILTER, newText);

        }
        mAlbumListLoaded = false;
        mArtistListLoaded = false;
        mSongListLoaded = false;
        getSupportLoaderManager().restartLoader(0, args, mAlbumLoaderCallbacks);
        getSupportLoaderManager().restartLoader(1, args, mArtistLoaderCallbacks);
        getSupportLoaderManager().restartLoader(2, args, mSongLoaderCallbacks);
    }

    private void refresh() {
        refresh(null);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        return super.onOptionsItemSelected(item);
    }

    private void returnToMain(String action) {
        returnToMain(action, null);
    }

    private void returnToMain(String action, Bundle data) {
        Intent i = new Intent(action);
        if (data != null) {
            i.putExtras(data);
        }
        setResult(RESULT_OK, i);
        finish();
    }

    private void showEditorDialog(Album album) {
        AlbumEditorDialog dialog = AlbumEditorDialog.newInstance(album);
        dialog.setOnEditionSuccessListener(mOnEditionSuccessListener);
        dialog.show(getSupportFragmentManager(), "edit_album_tags");
    }

    private void showPlaylistPicker(final Album album) {
        PlaylistPicker picker = PlaylistPicker.newInstance();
        picker.setListener(new PlaylistPicker.OnPlaylistPickedListener() {
            @Override
            public void onPlaylistPicked(Playlist playlist) {
                Playlists.addAlbumToPlaylist(getContentResolver(), playlist.getId(), album.getId());
            }
        });
        picker.show(getSupportFragmentManager(), "pick_playlist");

    }

    class AlbumViewHolder extends RecyclerView.ViewHolder implements OnClickListener {

        ImageView vArtwork;
        TextView vName;
        TextView vArtist;

        public AlbumViewHolder(View itemView) {
            super(itemView);
            vArtwork = (ImageView) itemView.findViewById(R.id.album_artwork);
            vName = (TextView) itemView.findViewById(R.id.album_name);
            vArtist = (TextView) itemView.findViewById(R.id.artist_name);
            vArtwork.setOnClickListener(this);
            itemView.findViewById(R.id.album_info).setOnClickListener(this);
            ImageButton menuButton = (ImageButton) itemView.findViewById(R.id.menu_button);
            menuButton.setOnClickListener(this);

            boolean dark = ThemeHelper.isDarkThemeSelected(SearchActivity.this);

            if (!dark) {
                Drawable drawable = menuButton.getDrawable();

                drawable.mutate();
                drawable.setColorFilter(getResources().getColor(R.color.primary_text), PorterDuff.Mode.SRC_ATOP);
            }

        }

        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();

            Album album = (Album) mAdapter.getItem(position);

            switch (v.getId()) {
            case R.id.album_info:
                Log.d("album", "album id " + album.getId() + " " + album.getAlbumName());
                Bundle data = new Bundle();
                data.putLong(MainActivity.ALBUM_ID, album.getId());
                data.putString(MainActivity.ALBUM_NAME, album.getAlbumName());
                data.putString(MainActivity.ALBUM_ARTIST, album.getArtistName());
                data.putInt(MainActivity.ALBUM_YEAR, album.getYear());
                data.putInt(MainActivity.ALBUM_TRACK_COUNT, album.getTrackCount());
                returnToMain(MainActivity.ACTION_SHOW_ALBUM, data);
                break;
            case R.id.menu_button:
                showMenu(album, v);
                break;

            }
        }

        private void showMenu(final Album album, View v) {

            PopupMenu popup = new PopupMenu(SearchActivity.this, v);
            MenuInflater inflater = popup.getMenuInflater();
            inflater.inflate(R.menu.album_list_item, popup.getMenu());
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {

                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    switch (item.getItemId()) {

                    case R.id.action_edit_tags:
                        showEditorDialog(album);
                        return true;
                    case R.id.action_add_to_playlist:
                        showPlaylistPicker(album);
                        return true;
                    }
                    return false;
                }
            });
            popup.show();
        }
    }

    class ArtistViewHolder extends RecyclerView.ViewHolder implements OnClickListener {

        TextView vName;
        TextView vAlbumCount;
        ImageView vArtistImage;

        public ArtistViewHolder(View itemView) {
            super(itemView);
            vName = (TextView) itemView.findViewById(R.id.artist_name);
            vAlbumCount = (TextView) itemView.findViewById(R.id.album_count);
            vArtistImage = (ImageView) itemView.findViewById(R.id.artist_image);
            itemView.setOnClickListener(this);

        }

        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();

            Artist artist = (Artist) mAdapter.getItem(position);

            Bundle data = new Bundle();
            data.putLong(MainActivity.ARTIST_ARTIST_ID, artist.getId());
            data.putString(MainActivity.ARTIST_ARTIST_NAME, artist.getName());
            data.putInt(MainActivity.ARTIST_ALBUM_COUNT, artist.getAlbumCount());
            data.putInt(MainActivity.ARTIST_TRACK_COUNT, artist.getTrackCount());
            returnToMain(MainActivity.ACTION_SHOW_ARTIST, data);
        }
    }

    class SongViewHolder extends RecyclerView.ViewHolder implements OnClickListener {

        TextView vTitle;
        TextView vArtist;
        ImageView vArtwork;

        private ID3TagEditorDialog.OnTagsEditionSuccessListener mOnTagsEditionSuccessListener = new ID3TagEditorDialog.OnTagsEditionSuccessListener() {
            @Override
            public void onTagsEditionSuccess() {
                returnToMain(MainActivity.ACTION_REFRESH);

            }
        };

        public SongViewHolder(View itemView) {
            super(itemView);
            vTitle = (TextView) itemView.findViewById(R.id.title);
            vArtist = (TextView) itemView.findViewById(R.id.artist);
            vArtwork = (ImageView) itemView.findViewById(R.id.artwork);
            itemView.findViewById(R.id.item_view).setOnClickListener(this);

            ImageButton menuButton = (ImageButton) itemView.findViewById(R.id.menu_button);
            menuButton.setOnClickListener(this);

            boolean dark = ThemeHelper.isDarkThemeSelected(SearchActivity.this);

            if (!dark) {
                Drawable drawable = menuButton.getDrawable();

                drawable.mutate();
                drawable.setColorFilter(getResources().getColor(R.color.primary_text), PorterDuff.Mode.SRC_ATOP);
            }

        }

        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();

            Song song = (Song) mAdapter.getItem(position);
            switch (v.getId()) {
            case R.id.item_view:

                selectSong(song);
                break;
            case R.id.menu_button:
                showMenu(song, v);
                break;
            }
        }

        private void showMenu(final Song song, View v) {
            PopupMenu popup = new PopupMenu(SearchActivity.this, v);
            MenuInflater inflater = popup.getMenuInflater();
            inflater.inflate(R.menu.song_list_item, popup.getMenu());
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {

                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    Bundle data;
                    switch (item.getItemId()) {
                    case R.id.action_add_to_queue:
                        data = songToBundle(song);
                        returnToMain(MainActivity.ACTION_ADD_TO_QUEUE, data);
                        return true;
                    case R.id.action_set_as_next_track:
                        data = songToBundle(song);
                        returnToMain(MainActivity.ACTION_SET_AS_NEXT_TRACK, data);
                        return true;
                    case R.id.action_edit_tags:
                        showID3TagEditor(song);
                        return true;
                    case R.id.action_add_to_playlist:
                        showPlaylistPicker(song);
                        return true;
                    }
                    return false;
                }
            });
            popup.show();
        }

        private void showID3TagEditor(Song song) {
            ID3TagEditorDialog dialog = ID3TagEditorDialog.newInstance(song);
            dialog.setOnTagsEditionSuccessListener(mOnTagsEditionSuccessListener);
            dialog.show(getSupportFragmentManager(), "edit_tags");
        }

        private void showPlaylistPicker(final Song song) {
            PlaylistPicker picker = PlaylistPicker.newInstance();
            picker.setListener(new PlaylistPicker.OnPlaylistPickedListener() {
                @Override
                public void onPlaylistPicked(Playlist playlist) {
                    Playlists.addSongToPlaylist(getContentResolver(), playlist.getId(), song.getId());
                }
            });
            picker.show(getSupportFragmentManager(), "pick_playlist");

        }

        private void selectSong(Song song) {
            Bundle data = songToBundle(song);

            returnToMain(MainActivity.ACTION_PLAY_SONG, data);
        }

        private Bundle songToBundle(Song song) {
            Bundle data = new Bundle();
            data.putLong(MainActivity.SONG_ID, song.getId());
            data.putString(MainActivity.SONG_TITLE, song.getTitle());
            data.putString(MainActivity.SONG_ARTIST, song.getArtist());
            data.putString(MainActivity.SONG_ALBUM, song.getAlbum());
            data.putLong(MainActivity.SONG_ALBUM_ID, song.getAlbumId());
            data.putInt(MainActivity.SONG_TRACK_NUMBER, song.getTrackNumber());
            return data;
        }

    }

    class SectionViewHolder extends RecyclerView.ViewHolder {

        TextView vSection;

        public SectionViewHolder(View itemView) {
            super(itemView);
            vSection = (TextView) itemView;
        }

    }

    class SearchAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

        private static final int ALBUM = 1;
        private static final int ARTIST = 2;
        private static final int SONG = 3;
        private static final int SECTION_ALBUMS = 4;
        private static final int SECTION_ARTISTS = 5;
        private static final int SECTION_SONGS = 6;

        private List<Album> mAlbumList = Collections.synchronizedList(new ArrayList<Album>());
        private List<Artist> mArtistList = Collections.synchronizedList(new ArrayList<Artist>());
        private List<Song> mSongList = Collections.synchronizedList(new ArrayList<Song>());

        public void setAlbumList(List<Album> albumList) {
            mAlbumList.clear();
            mAlbumList.addAll(albumList);
            refreshIfNecessary();
        }

        private void refreshIfNecessary() {
            if (mAlbumListLoaded && mArtistListLoaded && mSongListLoaded) {
                notifyDataSetChanged();
            }
        }

        public void setArtistList(List<Artist> artistList) {
            mArtistList.clear();
            mArtistList.addAll(artistList);
            refreshIfNecessary();
        }

        public void setSongList(List<Song> songList) {
            mSongList.clear();
            mSongList.addAll(songList);
            refreshIfNecessary();
        }

        public Object getItem(int position) {
            int albumRows = mAlbumList.size() > 0 ? mAlbumList.size() + 1 : 0;

            if (albumRows > position && position != 0) {

                return mAlbumList.get(position - 1);

            }
            int artistRows = mArtistList.size() > 0 ? mArtistList.size() + 1 : 0;
            if (albumRows + artistRows > position && position - albumRows != 0) {
                return mArtistList.get(position - albumRows - 1);
            }
            int songRows = mSongList.size() > 0 ? mSongList.size() + 1 : 0;
            if (albumRows + artistRows + songRows > position && position - albumRows - artistRows != 0) {
                return mSongList.get(position - albumRows - artistRows - 1);
            }
            return null;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int type) {

            View itemView;
            RecyclerView.ViewHolder viewHolder;

            switch (type) {
            case ALBUM:
                itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.album_list_item, parent,
                        false);

                viewHolder = new AlbumViewHolder(itemView);
                return viewHolder;
            case ARTIST:
                itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.artist_list_item, parent,
                        false);

                viewHolder = new ArtistViewHolder(itemView);
                return viewHolder;
            case SONG:
                itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.song_list_item, parent, false);

                viewHolder = new SongViewHolder(itemView);
                return viewHolder;

            case SECTION_ALBUMS:
            case SECTION_ARTISTS:
            case SECTION_SONGS:
                itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.section, parent, false);
                viewHolder = new SectionViewHolder(itemView);
                return viewHolder;
            }
            return null;
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
            int type = getItemViewType(position);
            int albumRows = mAlbumList.size() > 0 ? mAlbumList.size() + 1 : 0;

            int artistRows = mArtistList.size() > 0 ? mArtistList.size() + 1 : 0;

            switch (type) {
            case ALBUM:
                Album album = mAlbumList.get(position - 1);
                ((AlbumViewHolder) viewHolder).vName.setText(album.getAlbumName());
                ((AlbumViewHolder) viewHolder).vArtist.setText(album.getArtistName());

                ((AlbumViewHolder) viewHolder).vArtwork.setTag(position);

                ArtworkCache.getInstance().loadBitmap(album.getId(), ((AlbumViewHolder) viewHolder).vArtwork,
                        mThumbSize, mThumbSize);

                break;
            case ARTIST:
                Artist artist = mArtistList.get(position - albumRows - 1);
                ((ArtistViewHolder) viewHolder).vName.setText(artist.getName());
                ((ArtistViewHolder) viewHolder).vAlbumCount.setText(getResources()
                        .getQuantityString(R.plurals.albums_count, artist.getAlbumCount(), artist.getAlbumCount()));

                ((ArtistViewHolder) viewHolder).vArtistImage.setTag(position);

                ArtistImageCache.getInstance().loadBitmap(artist.getName(),
                        ((ArtistViewHolder) viewHolder).vArtistImage, mThumbSize, mThumbSize);
                break;
            case SONG:

                Song song = mSongList.get(position - albumRows - artistRows - 1);

                ((SongViewHolder) viewHolder).vTitle.setText(song.getTitle());
                ((SongViewHolder) viewHolder).vArtist.setText(song.getArtist());

                ((SongViewHolder) viewHolder).vArtwork.setTag(position);

                ArtworkCache.getInstance().loadBitmap(song.getAlbumId(), ((SongViewHolder) viewHolder).vArtwork,
                        mThumbSize, mThumbSize);
                break;
            case SECTION_ALBUMS:
                ((SectionViewHolder) viewHolder).vSection.setText(R.string.albums);

                break;
            case SECTION_ARTISTS:
                ((SectionViewHolder) viewHolder).vSection.setText(R.string.artists);

                break;
            case SECTION_SONGS:
                ((SectionViewHolder) viewHolder).vSection.setText(R.string.titles);

                break;
            }

        }

        @Override
        public int getItemViewType(int position) {
            int albumRows = mAlbumList.size() > 0 ? mAlbumList.size() + 1 : 0;

            if (albumRows > position) {
                if (position == 0) {
                    return SECTION_ALBUMS;
                }
                return ALBUM;
            }
            int artistRows = mArtistList.size() > 0 ? mArtistList.size() + 1 : 0;
            if (albumRows + artistRows > position) {
                if (position - albumRows == 0) {
                    return SECTION_ARTISTS;
                }
                return ARTIST;
            }
            int songRows = mSongList.size() > 0 ? mSongList.size() + 1 : 0;
            if (albumRows + artistRows + songRows > position) {
                if (position - albumRows - artistRows == 0) {
                    return SECTION_SONGS;
                }
                return SONG;
            }
            return 0;
        }

        @Override
        public int getItemCount() {

            int count = 0;
            if (mAlbumList.size() > 0) {
                count += mAlbumList.size() + 1;
            }
            if (mArtistList.size() > 0) {
                count += mArtistList.size() + 1;
            }
            if (mSongList.size() > 0) {
                count += mSongList.size() + 1;
            }
            return count;

        }

    }
}