package com.cinderella.musicsearch;
import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
public class SearchActivity extends ListActivity {
public static Mp3ListWrapper sData;
private static SogouMusicSearcher sFetcher;
private static FetchMp3ListTask sFetchMp3ListTask;
private static SearchActivity sSearchActivity;
private static String sQuery;
private Mp3ListAdapter mAdapter;
private TextView mSearchMessage;
private ProgressBar mProgressBar;
private Button mRetryButton;
private SearchListFooterView mFooter;
private SearchBar mSearchBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sSearchActivity = this;
setContentView(R.layout.search_list);
AdListener.createAds(this);
mProgressBar = (ProgressBar) findViewById(R.id.search_progress);
mSearchMessage = (TextView) findViewById(R.id.search_message);
mRetryButton = (Button) findViewById(R.id.retry_button);
mFooter = new SearchListFooterView(this);
getListView().addFooterView(mFooter);
mFooter.setFocusable(false);
mSearchBar = new SearchBar(this);
mFooter.getBtnPre().setOnClickListener(new onPrevClickListener());
mFooter.getBtnNext().setOnClickListener(new onNextClickListener());
mRetryButton.setOnClickListener(new onRetryClickListener());
setHintStatus();
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this, MusicPageActivity.class);
intent.putExtra(Const.INDEX, position);
startActivity(intent);
}
private void handleSearchResult(ArrayList<MusicInfo> mp3List) {
Utils.D("curPage: "+sFetcher.getCurPage());
mFooter.getBtnNext().setPressed(false);
mFooter.getBtnPre().setPressed(false);
if (sFetcher.getCurPage() <= 1) {
mFooter.getBtnPre().setEnabled(false);
} else {
mFooter.getBtnPre().setEnabled(true);
}
if (mAdapter == null) {
mAdapter = new Mp3ListAdapter(SearchActivity.this, R.layout.result_item);
setListAdapter(mAdapter);
}
if (mp3List != null) {
if (sData == null) {
sData = new Mp3ListWrapper();
}
if (mp3List.size() > 0) {
sData.append(mp3List);
} else {
setNoResultStatus();
}
mAdapter.notifyDataSetChanged();
} else {
setErrorStatus();
mAdapter.notifyDataSetChanged();
}
}
private static void fetchNextMp3ListBatch() {
if (sFetchMp3ListTask != null)
sFetchMp3ListTask.cancel(true);
sFetchMp3ListTask = new FetchMp3ListTask(true);
sFetchMp3ListTask.execute();
}
private static void fetchPrevMp3ListBatch() {
if (sFetchMp3ListTask != null)
sFetchMp3ListTask.cancel(true);
sFetchMp3ListTask = new FetchMp3ListTask(false);
sFetchMp3ListTask.execute();
}
private final class Mp3ListAdapter extends BaseAdapter {
private int mResource;
private LayoutInflater mInflater;
public Mp3ListAdapter(Context context, int resource) {
mResource = resource;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
if (sData == null) {
return 0;
} else {
return sData.size();
}
}
@Override
public Object getItem(int position) {
if (sData == null) {
return null;
} else {
return sData.get(position);
}
}
@Override
public long getItemId(int position) {
if (sData == null) {
return -1;
} else {
return position;
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v;
Object item = sData.get(position);
if (convertView == null) {
v = mInflater.inflate(mResource, parent, false);
} else {
v = convertView;
}
MusicInfo info = (MusicInfo) item;
((TextView) v.findViewById(R.id.title)).setText(info.getTitle());
((TextView) v.findViewById(R.id.artist)).setText(info.getArtist());
((TextView) v.findViewById(R.id.album)).setText(info.getAlbum());
((TextView) v.findViewById(R.id.size)).setText("Size: "+info.getDisplayFileSize());
return v;
}
}
// A thread safe wrapper around ArrayList<MP3Info>.
public final class Mp3ListWrapper {
private ArrayList<MusicInfo> mMp3List;
private ReadWriteLock lock = new ReentrantReadWriteLock();
private Lock r = lock.readLock();
private Lock w = lock.writeLock();
public Mp3ListWrapper() {
mMp3List = new ArrayList<MusicInfo>();
}
public void clear() {
w.lock();
try {
mMp3List.clear();
if (mAdapter != null)
mAdapter.notifyDataSetInvalidated();
} finally {
w.unlock();
}
}
public void add(MusicInfo info) {
w.lock();
try {
mMp3List.add(info);
if (mAdapter != null)
mAdapter.notifyDataSetChanged();
} finally {
w.unlock();
}
}
public void append(ArrayList<MusicInfo> mp3List) {
w.lock();
try {
mMp3List.addAll(mp3List);
mAdapter.notifyDataSetChanged();
} finally {
w.unlock();
}
}
public int size() {
r.lock();
try {
return mMp3List.size();
} finally {
r.unlock();
}
}
public MusicInfo get(int i) {
r.lock();
try {
return mMp3List.get(i);
} finally {
r.unlock();
}
}
}
private static class FetchMp3ListTask extends AsyncTask<Void, Void, ArrayList<MusicInfo>> {
boolean mIsNext;
public FetchMp3ListTask(boolean isNext) {
super();
mIsNext = isNext;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
if (sData != null) {
sData.clear();
}
sSearchActivity.setLoadingStatus();
}
@Override
protected void onPostExecute(ArrayList<MusicInfo> mp3List) {
sFetchMp3ListTask = null;
if (sSearchActivity != null) {
sSearchActivity.handleSearchResult(mp3List);
}
}
@Override
protected ArrayList<MusicInfo> doInBackground(Void... params) {
if (mIsNext) {
return sFetcher.getNextResultList();
} else {
return sFetcher.getPrevResultList();
}
}
}
private static class onPrevClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
sSearchActivity.fetchPrevMp3ListBatch();
}
}
private static class onNextClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
sSearchActivity.fetchNextMp3ListBatch();
}
}
private static class onRetryClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
sSearchActivity.fetchPrevMp3ListBatch();
}
}
public void notifyDataSetInvalidated() {
if (mAdapter != null)
mAdapter.notifyDataSetInvalidated();
}
public static void startQuery(String keyWords) {
if (!TextUtils.isEmpty(keyWords)) {
sSearchActivity.setLoadingStatus();
sQuery = keyWords;
sData = null;
if (sSearchActivity != null)
sSearchActivity.notifyDataSetInvalidated();
sFetcher = new SogouMusicSearcher();
sFetcher.setQuery(keyWords);
fetchNextMp3ListBatch();
} else {
sFetchMp3ListTask = null;
sFetcher = null;
}
}
public static void handleMp3ListIntent(Context context, String keyWords) {
Intent intent = new Intent(context, SearchActivity.class);
intent.putExtra(Const.QUERY, keyWords);
context.startActivity(intent);
}
public void setHintStatus() {
mProgressBar.setVisibility(View.GONE);
mSearchMessage.setVisibility(View.VISIBLE);
mRetryButton.setVisibility(View.GONE);
mSearchMessage.setText(R.string.search_hit);
}
public void setLoadingStatus() {
mProgressBar.setVisibility(View.VISIBLE);
mSearchMessage.setVisibility(View.VISIBLE);
mRetryButton.setVisibility(View.GONE);
mSearchMessage.setText(this.getString(R.string.searching_wait)+ " " + sQuery);
}
public void setNoResultStatus() {
mProgressBar.setVisibility(View.GONE);
mSearchMessage.setVisibility(View.VISIBLE);
mRetryButton.setVisibility(View.GONE);
mSearchMessage.setText(R.string.no_result_sorry);
}
public void setErrorStatus() {
mProgressBar.setVisibility(View.GONE);
mSearchMessage.setVisibility(View.VISIBLE);
mRetryButton.setVisibility(View.VISIBLE);
mSearchMessage.setText(R.string.network_error_retry);
}
}