• 学习Jammendo代码的心路历程(二)ViewFlipper数据的填充


    打开Jammendo进入到首页之后,会看到这样一个界面。可以看到下左效果,我们可以看到,他是上部分的ViewFlipper模块和下半部分的listview模块构成的,今天就简单的说一下JammendoViewFlipper是如何加载实际的图片的

    我们可以看到上面的ViewFlipper模块中有很多图片,这个模块第一次初始化的时候,实际作用可以理解为是——获取这个星期内最流行的专辑,并在ViewFlipper模块中展示

    主界面功能在Jammendo中是在HomeActivity中实现的,可以看下他的布局文件

     main.xml文件

    <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>

      在Jammendo中,他自定义了一个继承于ViewFlipper的FixedViewFlipper控件,并且在代码中重写了onDetachedFromWindow方法。在此,他重写这个方法的目的是为了防止一个bug的出现,可以参考下面这篇文章                               http://blog.sina.com.cn/s/blog_74c22b2101012urv.html

      我们可以看到在FixedViewFlipper控件中又包含了三个LinerLayerout布局,它们的作用分别如下:  

      (1)Loading:当图片加载比较慢的时候,会在ViewFlipper显示Loading字样

      (2)Gallery:Gallery是一个滑动图片展示控件,如何客户端可以成功从服务器获取数据,会将在这个控件中展示获取专辑内容

      (3)Fialure:客户端信息获取失败时,会提示加载失败

      让我们会到HomeActivity文件,在HomeActivity的OnCreate()方法中存在我们可以看到这样一段代码

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

      这里的NewsTask是继承于AsyncTask的一个类,执行异步操作。异步操作的意义在于我们可以将一些比较费时的操作放在这里执行,提高整体工作效率。在这里,我们将客户端请求服务器端数据,并将数据显示到FixedViewFlipper这样一个过程放在这里执行。

      首先简单分析一下AsyncTask中一些基本方法的意义:

      (1)onPreExecute():在执行doingBackground方法前会执行这个方法,可以显示一些进度条之类的

      (2)doinBackground():耗费时间的动作主要在这个方法中执行

      (3)publicProgress():用来更新任务进度

      (4)onProgressUpdate():当publicProgress方法被调用时,UI线程将调用这个方法在界面上展示任务的进展情况

      (5)onPostExecute():任务执行完成,返回结果

    private class NewsTask extends AsyncTask<Void, WSError, Album[]> {
    
    		@Override
    		public void onPreExecute() {
    			mViewFlipper.setDisplayedChild(0);	     // 默认显示ViewFlipper中第一个界面
    			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);	//	显示ViewFlipper中第二个界面
    				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);
    		}
    		
    	}

      在onPreExecute()方法中,我们可以看到,他这里执行了一个让FixedViewFlipper显示loading界面的功能

      doinBackground()方法主要完成了从服务器获取专辑信息的动作

      onPostExecute(),将当前获取数据绑定到Gallery控件之上,完成专辑信息的显示

      onProgressUpdate()如果发生异常,会弹出一个对话框提示

      下面我们主要分析一下doinBackground()函数到底干了些什么?

      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;
    		}
    

      首先创建了一个JamendoGet2Api对象,然后定义了一个Album[]数组,在这里的Album[]其实存放的就是我们将要从服务器上获取的专辑信息

      下面调用server中的getPopularAlbumsWeek()获取专辑信息

       跳转到getPopularAlbumsWeek()方法

    	private String doGet(String query) throws WSError{
    		return Caller.doGet(GET_API + query);
    	}
    
    	@Override
    	public Album[] getPopularAlbumsWeek() throws JSONException, WSError {
    		
    		String jsonString = doGet("id+name+url+image+rating+artist_name/album/json/?n=20&order=ratingweek_desc");
    		if (jsonString == null)
    			return null;
    		
    		try {
    			JSONArray jsonArrayAlbums = new JSONArray(jsonString); 
    			return AlbumFunctions.getAlbums(jsonArrayAlbums);
    		} catch (NullPointerException e) {
    			e.printStackTrace();
    			throw new JSONException(e.getLocalizedMessage());
    		}
    	}
    

      getPopularAlbumsWeek中定义了一个jsonString来保存从从服务器上获取的数据,调用的doGet方法是在Caller类中定义,在这里只是传递了后面一些的参数信息

      跳转到Caller类中的doGet()方法中我们可以发现,他就是通常的json从服务器端获取数据的一个封装,值得我们注意的是他这里的Cache机制,当他收到当前url信息时,会先遍历本地的cache数据,如果本地存在,则不再去访问服务器获取数据。如果不存在于本地,则从服务端获取数据,并数据转换为String类型。

             String data = null;
    		if(requestCache != null){
    			data = requestCache.get(url);
    			if(data != null){
    				Log.d(JamendoApplication.TAG, "Caller.doGet [cached] "+url);
    				return data;
    			}
    		}
    

      之后我们只需要一步步返回,便完成了从服务器端获取最近一个火爆专辑信息的获取。

      

  • 相关阅读:
    前序遍历和中序遍历树构造二叉树
    2014百度之星初赛第一场部分题解
    爬虫小记--抓取过程简要分析
    前端程序猿必知:单页面应用的核心
    swift -类的定义及使用
    【Unity优化】怎样实现Unity编辑器中的协程
    poj 1125 (floyed 最短路径)
    Android API Guides---Tasks and Back Stack
    循环-16. 猴子吃桃问题(15)
    零java基础搞定微信Server
  • 原文地址:https://www.cnblogs.com/cfyrwang/p/4432253.html
Copyright © 2020-2023  润新知