開源Jamendo在線音樂播放器源碼(三)


這里首先顯示我們的主界面圖片共大家理解。

一步步走到了我們的主界面,首先我們看看主界面的布局文件main.xml

View Code
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2009 Teleca Poland Sp. z o.o. <android@teleca.com>

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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation
="vertical" android:layout_width="fill_parent"
android:layout_height
="fill_parent" android:background="#ffffff">

<com.teleca.jamendo.util.FixedViewFlipper
android:orientation="vertical" android:id="@+id/ViewFlipper"
android:layout_width
="fill_parent" android:layout_height="75dip"
android:background
="@drawable/gradient_dark_purple">

<!-- (0) Loading -->
<LinearLayout android:orientation="vertical"
android:layout_width
="fill_parent" android:layout_height="fill_parent"
android:layout_marginLeft
="15dip" android:gravity="left|center_vertical">
<com.teleca.jamendo.widget.ProgressBar
android:id="@+id/ProgressBar" android:layout_width="wrap_content"
android:layout_height
="wrap_content">
</com.teleca.jamendo.widget.ProgressBar>
</LinearLayout>

<!-- (1) Gallery -->
<LinearLayout android:orientation="vertical"
android:layout_width
="fill_parent" android:layout_height="fill_parent"
android:gravity
="center">
<Gallery android:id="@+id/Gallery" android:layout_width="fill_parent"
android:layout_height
="wrap_content" android:spacing="0px" />
</LinearLayout>

<!-- (2) Failure -->
<LinearLayout android:orientation="vertical"
android:layout_width
="fill_parent" android:layout_height="fill_parent"
android:layout_marginLeft
="15dip" android:gravity="left|center_vertical">
<com.teleca.jamendo.widget.FailureBar
android:id="@+id/FailureBar" android:layout_width="wrap_content"
android:layout_height
="wrap_content">
</com.teleca.jamendo.widget.FailureBar>
</LinearLayout>
</com.teleca.jamendo.util.FixedViewFlipper>

<android.gesture.GestureOverlayView
xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gestures"
android:layout_width
="fill_parent" android:layout_height="fill_parent"

android:gestureStrokeType
="multiple"
android:eventsInterceptionEnabled
="false" android:orientation="vertical">

<ListView android:id="@+id/HomeListView"
android:layout_width
="fill_parent" android:layout_height="fill_parent"
android:divider
="#000" />
</android.gesture.GestureOverlayView>

</LinearLayout>

我們可以看到在LinearLayout中嵌套了2欄,第一個是com.teleca.jamendo.util.FixedViewFlipper,第二個是手勢視圖android.gesture.GestureOverlayView,。默認是垂直顯示分欄。

首先來看看com.teleca.jamendo.util.FixedViewFlipper,這是一個自定義控件,繼承之ViewFlipper,是作為切換視圖所用,一次只能顯示一個View內容。

FixedViewFlipper代碼如下:

View Code
public class FixedViewFlipper extends ViewFlipper {

public FixedViewFlipper(Context context) {
super(context);
}

public FixedViewFlipper(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void onDetachedFromWindow() {

int apiLevel = Build.VERSION.SDK_INT;

if (apiLevel >= 7) {
try {
super.onDetachedFromWindow();
} catch (IllegalArgumentException e) {
Log.w("Jamendo", "Android project issue 6191 workaround.");
/* Quick catch and continue on api level 7, the Eclair 2.1 */
} finally {
super.stopFlipping();
}
} else {
super.onDetachedFromWindow();
}
}
}

我們看到它基本沒有什么特殊之處,只是重寫了onDetachedFromWindow方法。該方法的作用是當view離開窗口時調用。這里判斷了SDK版本,同時停止切換View.

我們已經知道ViewFlipper類似於FrameLayout,一次只顯示一個View的內容。知道這一點后,我們再看看我們的布局文件中com.teleca.jamendo.util.FixedViewFlipper內部布局:

我們可以看到,里面共有三部分內容:Loading,Gallery,Failure。分別是加載中,顯示Gallery圖像列表,加載失敗界面。

剛進來的時候當然默認顯示加載界面,加載Gallery數據時,但是由於網絡太快,基本上一閃而過,如果網絡太慢,它就顯示出來了,如果加載失敗,就會顯示加載失敗界面。

我們怎么知道它是顯示哪部分界面的呢?

我們先來看看HomeActivity的類結構以及繼承關系吧。

它實現了OnAlbumClickListener接口,還有2個內部任務類。一個是獲取最新專輯,一個是獲取最近前100手歌曲。

好了現在看看onCreate方法:

View Code
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);

mHomeListView = (ListView)findViewById(R.id.HomeListView);
mGallery = (Gallery)findViewById(R.id.Gallery);
mProgressBar = (ProgressBar)findViewById(R.id.ProgressBar);
mFailureBar = (FailureBar)findViewById(R.id.FailureBar);
mViewFlipper = (ViewFlipper)findViewById(R.id.ViewFlipper);

mGestureOverlayView = (GestureOverlayView) findViewById(R.id.gestures);
mGestureOverlayView.addOnGesturePerformedListener(JamendoApplication
.getInstance().getPlayerGestureHandler());

new NewsTask().execute((Void)null);
}

 方法中主要是實例化布局文件main.xml中的控件,當然最重要的有2點,第1點:實例化手勢圖層,並添加手勢感知監聽。第2點:執行NewsTask任務獲取專輯列表。

 這里首先講解NewsTask任務類,因為這里決定我們顯示的是加載還是Gallery列表界面或者是失敗界面。代碼如:

View Code
/**
* Executes news download, JamendoGet2Api.getPopularAlbumsWeek
*
*
@author Lukasz Wisniewski
*/
private class NewsTask extends AsyncTask<Void, WSError, Album[]> {

@Override
public void onPreExecute() {
mViewFlipper.setDisplayedChild(0);
mProgressBar.setText(R.string.loading_news);
super.onPreExecute();
}

@Override
public Album[] doInBackground(Void... params) {
JamendoGet2Api server = new JamendoGet2ApiImpl();
Album[] albums = null;
try {
albums = server.getPopularAlbumsWeek();
} catch (JSONException e) {
e.printStackTrace();
} catch (WSError e){
publishProgress(e);
}
return albums;
}

@Override
public void onPostExecute(Album[] albums) {

if(albums != null && albums.length > 0){
mViewFlipper.setDisplayedChild(1);
ImageAdapter albumsAdapter = new ImageAdapter(HomeActivity.this);
albumsAdapter.setList(albums);
mGallery.setAdapter(albumsAdapter);
mGallery.setOnItemClickListener(mGalleryListener);
mGallery.setSelection(albums.length/2, true); // animate to center

} else {
mViewFlipper.setDisplayedChild(2);
mFailureBar.setOnRetryListener(new OnClickListener(){

@Override
public void onClick(View v) {
new NewsTask().execute((Void)null);
}

});
mFailureBar.setText(R.string.connection_fail);
}
super.onPostExecute(albums);
}

@Override
protected void onProgressUpdate(WSError... values) {
Toast.makeText(HomeActivity.this, values[0].getMessage(), Toast.LENGTH_LONG).show();
super.onProgressUpdate(values);
}

NewsTask繼承AsyncTask,異步任務,通常我們獲取后台數據就是通過繼承這個任務類,在任務中獲取后台數據,而不是新建個Thread,然后再結合Handler,然后通過Handler與主UI線程交互顯示數據,這樣比較麻煩,使用AsyncTask簡單多了,雖然它內部也是由Thread等等封裝的。

我們先看看執行任務前做了什么,

mViewFlipper.setDisplayedChild(0);
mProgressBar.setText(R.string.loading_news);

執行前?默認顯示ViewFlipper中第一個界面,同時設置進度條文字。

執行中呢?

@Override
public Album[] doInBackground(Void... params) {
JamendoGet2Api server = new JamendoGet2ApiImpl();
Album[] albums = null;
try {
albums = server.getPopularAlbumsWeek();
} catch (JSONException e) {
e.printStackTrace();
} catch (WSError e){
publishProgress(e);
}
return albums;
}

 哦,它是調用接口方法獲取服務器端專輯列表數據啊,這里他們進行了封裝獲取服務的接口以及實現,我們暫時不關注,只需知道它分離了獲取服務數據就行了。

執行后呢?

@Override
public void onPostExecute(Album[] albums) {

if(albums != null && albums.length > 0){
mViewFlipper.setDisplayedChild(1);
ImageAdapter albumsAdapter = new ImageAdapter(HomeActivity.this);
albumsAdapter.setList(albums);
mGallery.setAdapter(albumsAdapter);
mGallery.setOnItemClickListener(mGalleryListener);
mGallery.setSelection(albums.length/2, true); // animate to center

} else {
mViewFlipper.setDisplayedChild(2);
mFailureBar.setOnRetryListener(new OnClickListener(){

@Override
public void onClick(View v) {
new NewsTask().execute((Void)null);
}

});
mFailureBar.setText(R.string.connection_fail);
}
super.onPostExecute(albums);
}

原來獲取到專輯列表數據后,顯示ViewFlipper中第二個界面,也就是Gallery列表,當然顯示Gallery列表是通過Adpater設配器的,我們還看到如果獲取不到數據或者獲取數據失敗,那么它就會顯示ViewFlipper中第三個界面,就是我們的失敗界面,同時提供方法讓它可以再次執行任務來獲取服務端數據。

邏輯非常清晰。

接下來就來看看下一部分內容。




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM