<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>移动技术 &#187; Android开发</title>
	<atom:link href="http://www.newlifeclan.com/mobile/archives/category/android/feed" rel="self" type="application/rss+xml" />
	<link>http://www.newlifeclan.com/mobile</link>
	<description>又一个NewLifeClan站点</description>
	<lastBuildDate>Wed, 10 Jan 2024 09:33:26 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.0.38</generator>
	<item>
		<title>Android Studio下使用jar包</title>
		<link>http://www.newlifeclan.com/mobile/archives/286</link>
		<comments>http://www.newlifeclan.com/mobile/archives/286#comments</comments>
		<pubDate>Fri, 07 Dec 2018 06:21:06 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[Android开发]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/mobile/?p=286</guid>
		<description><![CDATA[<p>1. 把jar包复制到项目的lib目录下： 2. 在jar包上右键，弹出菜单的下方，点击 Add as Lib [&#8230;]</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/286">Android Studio下使用jar包</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>1. 把jar包复制到项目的lib目录下：<span id="more-286"></span></p>
<p><img class="alignnone size-full wp-image-287" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2018/12/1416675-b199e66c879cb53b.png" alt="1416675-b199e66c879cb53b" width="1000" height="531" /></p>
<p>2. 在jar包上右键，弹出菜单的下方，点击 Add as Libary，会帮助我们自动添加到build.gradle</p>
<p><img class="alignnone size-full wp-image-288" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2018/12/1416675-8bfadd01c274ecb9.png" alt="1416675-8bfadd01c274ecb9" width="1000" height="531" /></p>
<p>OK, 你可以使用了</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/286">Android Studio下使用jar包</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/mobile/archives/286/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>给AppCompatActivity的标题栏上加上返回按钮</title>
		<link>http://www.newlifeclan.com/mobile/archives/280</link>
		<comments>http://www.newlifeclan.com/mobile/archives/280#comments</comments>
		<pubDate>Tue, 04 Dec 2018 13:51:36 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[Android开发]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/mobile/?p=280</guid>
		<description><![CDATA[<p>目前基于android6.0版本sdk并通过android studio创建的空Activity默认都是继承自 [&#8230;]</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/280">给AppCompatActivity的标题栏上加上返回按钮</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>目前基于android6.0版本sdk并通过android studio创建的空Activity默认都是继承自AppCompatActivity。<span id="more-280"></span></p>
<p><img class="alignnone size-full wp-image-282" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2018/12/201612151100385241.png" alt="20161215110038524" width="631" height="590" /></p>
<p>在默认情况下，这个Activity在标题栏上是没有返回按钮的，如下图所示：</p>
<p><img class="alignnone size-full wp-image-283" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2018/12/20161215110203338.png" alt="20161215110203338" width="600" height="723" /></p>
<p>此时如果需要给AppCompatActivity的标题栏上加上返回按钮，可以在Activity的onCreate中加入如下代码：</p><pre class="crayon-plain-tag">android.support.v7.app.ActionBar actionBar = getSupportActionBar();
    if(actionBar != null){
        actionBar.setHomeButtonEnabled(true);
        actionBar.setDisplayHomeAsUpEnabled(true);
    }</pre><p>在onOptionsItemSelected中加入如下代码：</p><pre class="crayon-plain-tag">@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                this.finish(); // back button
                return true;
        }
        return super.onOptionsItemSelected(item);
    }</pre><p>运行效果，如下：</p>
<p><img class="alignnone size-full wp-image-284" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2018/12/20161215110357529.png" alt="20161215110357529" width="624" height="721" /></p>
<p>完整的示例代码如下：</p><pre class="crayon-plain-tag">package com.toby.personal.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        android.support.v7.app.ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            actionBar.setHomeButtonEnabled(true);
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                this.finish(); // back button
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

}</pre><p>&nbsp;</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/280">给AppCompatActivity的标题栏上加上返回按钮</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/mobile/archives/280/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>android之RecyclerView</title>
		<link>http://www.newlifeclan.com/mobile/archives/118</link>
		<comments>http://www.newlifeclan.com/mobile/archives/118#comments</comments>
		<pubDate>Fri, 06 Jan 2017 05:50:37 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[Android开发]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/mobile/?p=118</guid>
		<description><![CDATA[<p>RecyclerView并提供了向下的兼容库，也就是说5.0一下也可以使用它。 为什么叫做RecyclerVi [&#8230;]</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/118">android之RecyclerView</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>RecyclerView并提供了向下的兼容库，也就是说5.0一下也可以使用它。</p>
<p>为什么叫做RecyclerView呢？Recycler：资源回收。下面就是重点的解释：<span id="more-118"></span></p>
<ul>
<li>RecyclerView不关心Item是否显示在正确的位置，那如何显示呢？我们就需要引入LayoutManager用来显示RecyclerView的风格。他可以显示ListView、GridView、横向GridView、横向ListView还有瀑布流效果。</li>
<li>RecyclerView不关心Item间如何分隔的。我们需要用到ItemDecoration来绘制分割。</li>
<li>RecyclerView不关心Item增加与删除的动画效果。我们需要使用ItemAnimator来完成。</li>
</ul>
<p>这种插件式的玩法，也让RecyclerView仅仅关注如何回收和复用View。</p>
<p>下面还有一些与RecyclerView相关的重要类：</p>
<p>LayoutManager，ItemDecoration，ItemAnimator，Adapter，ViewHolder（强制使用）</p>
<p>&nbsp;</p>
<p>下面我们来实战一下：</p>
<h2>创建项目recyclerView，选择最小版本为5.1</h2>
<p>我们使用的android studio，当创建项目完成后，我们要导入包，通过File-&gt;Project Structure-&gt;app-&gt;Dependencies-&gt;左边上角+号，Library dependency-&gt;找到com.android.support:recyclerview-v7:*****</p>
<p>我们回到Project模式下的app-&gt;build.gradle文件中</p><pre class="crayon-plain-tag">dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support:recyclerview-v7:24.0.0'
}</pre><p>你可以看到recyclerview已经正式加入。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>使用</h2>
<p>android studio的Android模式</p>
<p><img class="alignnone size-full wp-image-119" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2017/01/20170106124109.png" alt="20170106124109" width="204" height="271" /></p>
<p>下来到res/Layout/activity_main.xml中：</p><pre class="crayon-plain-tag">&lt;android.support.v7.widget.RecyclerView
        android:id="@+id/id_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
         /&gt;</pre><p>下面来到MainActivity中：</p><pre class="crayon-plain-tag">public class MainActivity extends AppCompatActivity {

    //相关声明
    private RecyclerView mRecyclerView;
    private List&lt;String&gt; mDatas;
    private SimpleAdapter mAdapter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //加载数据
        initDatas();
        //初始化Views
        initViews();
    }

    private void initViews() {
        mRecyclerView=(RecyclerView) findViewById(R.id.id_recyclerview);
    }

    private void initDatas() {
        mDatas = new ArrayList&lt;String&gt;();

        //A-z的所有字母
        for(int i='A'; i&lt;='z';i++){
            mDatas.add(""+(char)i);
        }
    }
}</pre><p>上面的含义，我已添加注释，我们发现我们还缺少mAdapter没有被使用，那么就新建一个吧？</p>
<h2>创建Adapter</h2>
<p>首先MainActivity同包下创建一个</p><pre class="crayon-plain-tag">public class SimpleAdapter extends RecyclerView.Adapter&lt;MyViewHolder&gt; {</pre><p>并实现MyViewHolder，</p><pre class="crayon-plain-tag">class MyViewHolder extends ViewHolder {

    public MyViewHolder(View itemView) {
        super(itemView);
    }
}</pre><p>后面我还还会修改这个ViewHolder。</p>
<p>我们需要实现SimpleAdapter的几个必要方法：</p><pre class="crayon-plain-tag">public class SimpleAdapter extends RecyclerView.Adapter&lt;MyViewHolder&gt; {

    private LayoutInflater mInflater;
    //上下文
    private Context mContext;
    private List&lt;String&gt; mDatas;

    public SimpleAdapter(Context context, List&lt;String&gt; datas){
         this.mContext=context;
         this.mDatas=datas;
        //载入布局页面
        mInflater=LayoutInflater.from(context);
    }
    //创建ViewHolder
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        return null;
    }
    //绑定ViewHolder
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {

    }
    //获取item数
    @Override
    public int getItemCount() {
        return this.mDatas.size();
    }
}</pre><p>我们要完成onCreateViewHolder的方法，就需要创建一个视图xml：</p>
<p>在res/Layout中创建一个item_single_textview.xml文件。</p><pre class="crayon-plain-tag">&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:background="#44ff0000"
    android:layout_height="72dp"
    &gt;

    &lt;TextView
        android:id="@+id/id_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
         /&gt;
&lt;/FrameLayout&gt;</pre><p>&nbsp;</p>
<p>回到我们之前创建的SimpleAdapter:</p><pre class="crayon-plain-tag">//创建ViewHolder
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        /*
        inflate()的作用就是将一个用xml定义的布局文件查找出来，注意与findViewById()的区别，inflate是加载一个布局文件，而findViewById则是从布局文件中查找一个控件。
        关于LayoutInflater类inflate(int resource, ViewGroup root, boolean attachToRoot)方法三个参数的含义
        
        resource：需要加载布局文件的id，意思是需要将这个布局文件中加载到Activity中来操作。
        
        root：需要附加到resource资源文件的根控件，什么意思呢，就是inflate()会返回一个View对象，如果第三个参数attachToRoot为true，
        就将这个root作为根对象返回，否则仅仅将这个root对象的LayoutParams属性附加到resource对象的根布局对象上，
        也就是布局文件resource的最外层的View上，比如是一个LinearLayout或者其它的Layout对象。
        
        attachToRoot：是否将root附加到布局文件的根视图上
         */
        View view=mInflater.inflate(R.layout.item_single_textview,parent,false);
        MyViewHolder viewHolder = new MyViewHolder(view);
        return viewHolder;
    }</pre><p>返回需要的viewHolder。</p>
<p>我们现在就要完善之前的ViewHolder了：</p><pre class="crayon-plain-tag">class MyViewHolder extends ViewHolder {

    TextView tv;

    public MyViewHolder(View itemView) {
        super(itemView);
        tv= (TextView) itemView.findViewById(R.id.id_tv);
    }
}</pre><p>好我们来到simpleAdapter中，实现绑定</p><pre class="crayon-plain-tag">//绑定ViewHolder
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.tv.setText(mDatas.get(position));

    }</pre><p>也就是说，我们给textView绑定了相应的值。</p>
<p>&nbsp;</p>
<h2>来到MainActivity，使用我们新创建的Adapter：</h2>
<p></p><pre class="crayon-plain-tag">@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //加载数据
        initDatas();
        //初始化Views
        initViews();

        mAdapter=new SimpleAdapter(this,mDatas);
        mRecyclerView.setAdapter(mAdapter);

        LinearLayoutManager linearLayoutMangaer= new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
        mRecyclerView.setLayoutManager(linearLayoutMangaer);
    }</pre><p>LinearLayoutManager中的LinearLayoutManager.VERTICAL 表示垂直布局，整体就类似于Listview的垂直布局。</p>
<p><img class="alignnone size-full wp-image-122" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2017/01/20170106135428.png" alt="20170106135428" width="336" height="575" /></p>
<p>&nbsp;</p>
<h2>添加分割线</h2>
<p>你会发现我们上面运行的效果没有分割线，嘿嘿，这就要用到我们之前所说的ItemDecoration了：</p>
<p>因为google对这个类并没有默认的实现，所以我们找到了一个网络上使用率很高的公共类：</p>
<p>他的地址是：https://gist.github.com/alexfu/0f464fc3742f134ccd1e   估计你要翻墙才能得到，我直接复制到项目中了，大家可以随时复制使用：</p><pre class="crayon-plain-tag">package com.example.napoleon.recyclerview;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST &amp;&amp; orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i &lt; childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i &lt; childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}</pre><p>浏览一下这个类吧，mDivider:item间隔图片资源 ；mOrientation：方向，水平和垂直；onDraw方法会根据方向绘制；getItemOffsets提供绘制分割线的间隙。</p>
<p>来到ManActivity中的onCreate方法使用这个类：</p><pre class="crayon-plain-tag">//设置RecyclerView的布局管理
        LinearLayoutManager linearLayoutMangaer= new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
        mRecyclerView.setLayoutManager(linearLayoutMangaer);

        //设置RecyclerView的Item分隔符
        mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));</pre><p>运行我们的程序：</p>
<p><img class="alignnone size-full wp-image-124" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2017/01/20170106202409.png" alt="20170106202409" width="352" height="600" /></p>
<p>分割符已经有了。</p>
<p>&nbsp;</p>
<h2>MenuItem切换GridView效果和瀑布流</h2>
<p>我们下面想切换listView效果为GridView效果，需要MenuItem作为切换的中介。</p>
<p>首先，我们要创建Menu，在res目录下的menu文件夹下创建一个main.xml文件，内容如下：</p>
<p>&nbsp;</p><pre class="crayon-plain-tag">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
    &lt;item
        android:id="@+id/action_listview"
        android:orderInCategory="100"
        android:title="ListView" /&gt;
    &lt;item
        android:id="@+id/action_gridview"
        android:orderInCategory="100"
        android:title="GridView" /&gt;
    &lt;item
        android:id="@+id/action_hor_gridview"
        android:orderInCategory="100"
        android:title="HorizontalGridView" /&gt;
    &lt;item
        android:id="@+id/action_staggered"
        android:orderInCategory="100"
        android:title="StaggeredGridView" /&gt;

&lt;/menu&gt;</pre><p>注释：这里创建了两个菜单项，其中&lt;item&gt;标签就是用来创建具体的一个菜单项，然后通过android:id给这个菜单项指定一个唯一的标识符，通过android:title给这菜单指定一个名称。</p>
<p>然后打开Activity，重写onCreateOptionsMenu()方法，内容如下：</p><pre class="crayon-plain-tag">//通过getMenuInflater()方法得到MenuInflater对象
    public boolean onCreateOptionsMenu(Menu menu){
　　　　　//调用inflate()方法创建菜单
        getMenuInflater().inflate(R.menu.main,menu);
        //如果返回false，创建的菜单无法显示
        return true;
    }</pre><p>当然，仅仅让菜单显示出来是不够的，菜单不是用来看的，关键是要菜单真正可用才行，因此还要再定义菜单响应事件。</p>
<p>在Activity中重写onOptionsItemSelected()方法，内容如下：</p><pre class="crayon-plain-tag">public boolean onOptionsItemSelected(MenuItem item){
        //通过调用item.getItemId()来判断菜单项
        switch (item.getItemId()){
            case R.id.action_gridview:
                Toast.makeText(this,"You Clicked Add",Toast.LENGTH_SHORT).show();
                break;
            case R.id.action_listview:
                Toast.makeText(this,"You Clicked Add",Toast.LENGTH_SHORT).show();
                break;
            case R.id.action_staggered:
                Toast.makeText(this,"You Clicked Add",Toast.LENGTH_SHORT).show();
                break;
            case R.id.action_hor_gridview:
                Toast.makeText(this,"You Clicked Add",Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return true;
    }</pre><p>当然，仅仅让菜单显示出来是不够的，菜单不是用来看的，关键是要菜单真正可用才行，因此还要再定义菜单响应事件。</p>
<p>在Activity中重写onOptionsItemSelected()方法，内容如下：</p><pre class="crayon-plain-tag">public boolean onOptionsItemSelected(MenuItem item){
        //通过调用item.getItemId()来判断菜单项
        switch (item.getItemId()){
            case R.id.action_gridview:
                Toast.makeText(this,"You Clicked GridView",Toast.LENGTH_SHORT).show();
                break;
            case R.id.action_listview:
                Toast.makeText(this,"You Clicked Listview",Toast.LENGTH_SHORT).show();
                break;
            case R.id.action_staggered:
                Toast.makeText(this,"You Clicked Staggered",Toast.LENGTH_SHORT).show();
                break;
            case R.id.action_hor_gridview:
                Toast.makeText(this,"You Clicked HorizontalGridView",Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return true;
    }</pre><p>运行程序，并按下Menu键就能够显示菜单项了。</p>
<p>菜单默认是不会显示出来的，只有按下Menu键，菜单才会在显示出来。</p>
<p>&nbsp;</p>
<p>下面我们就来看看如何从ListView效果到GridView效果，其实代码是很简单的：</p><pre class="crayon-plain-tag">public boolean onOptionsItemSelected(MenuItem item){
        //通过调用item.getItemId()来判断菜单项
        switch (item.getItemId()){
            case R.id.action_gridview:
                Toast.makeText(this,"You Clicked GridView",Toast.LENGTH_SHORT).show();
                //new GridLayoutManager第二个参数为3列
                mRecyclerView.setLayoutManager(new GridLayoutManager(this,3));
                break;
            case R.id.action_listview:
                Toast.makeText(this,"You Clicked Listview",Toast.LENGTH_SHORT).show();
                //维持原来的listView效果
                mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
                break;
            case R.id.action_staggered:
                Toast.makeText(this,"You Clicked Staggered",Toast.LENGTH_SHORT).show();
                break;
            case R.id.action_hor_gridview:
                Toast.makeText(this,"You Clicked HorizontalGridView",Toast.LENGTH_SHORT).show();
                //new StaggeredGridLayoutManager()第一个参数为列数，第二个参数为方向横向GridView
                mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(5,StaggeredGridLayoutManager.HORIZONTAL));
                break;
            default:
        }
        return true;
    }</pre><p>我做了备注，可查看代码什么意思。</p>
<p><img class="alignnone size-full wp-image-125" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2017/01/20170106205606.png" alt="20170106205606" width="352" height="600" /></p>
<p>我们看到了GirdView。</p>
<p>但是当你切换到HorizontalGridView时，你发现没有GridView的效果，我们自需要控制res\layout\item_single_textview.xml的长度即可：</p><pre class="crayon-plain-tag">android:layout_width="72dp"</pre><p>可能会好很多，具体参数你可以根据你的需求来改变。</p>
<p>当然我们可以使用android:layout_margin=&#8221;3dp&#8221;来制作分隔样式。</p>
<p>&nbsp;</p>
<h2>实现瀑布流效果</h2>
<p>实现瀑布流效果，代码其实差不多，但是还要小小调整一下，所有我们先复制MainActivity另存为StaggeredGridLayoutActivity，复制SimpleAdapter为StaggeredAdapter。</p>
<p>我们主要要做的事情就是动态控制我们的item的高度。</p>
<p>来到刚复制的StaggeredAdapter中添加如下代码：</p><pre class="crayon-plain-tag">.....
    //声明存放随机高度
    private List&lt;Integer&gt; mHeights;

    public StaggeredAdapter(Context context, List&lt;String&gt; datas){
        .......
        //载入布局页面
        mInflater=LayoutInflater.from(context);

        //创建随机高度
        mHeights=new ArrayList&lt;Integer&gt;();
        for(int i=0; i &lt; mDatas.size();i++){
            mHeights.add((int)(100+Math.random()*300));
        }
    }</pre><p>绑定这些随机高度到ViewHolder</p><pre class="crayon-plain-tag">//绑定ViewHolder
    @Override
    public void onBindViewHolder(StaggeredAdapter.MyViewHolder holder, int position) {
        ViewGroup.LayoutParams lp=holder.itemView.getLayoutParams();
        lp.height=mHeights.get(position);
        holder.itemView.setLayoutParams(lp);

        holder.tv.setText(mDatas.get(position));

    }</pre><p><strong> 修改StaggeredGridLayoutActivity</strong></p>
<p>将StaggeredGridLayoutActivity中原来的SimpleAdapter更改为StaggeredAdapter。</p>
<p>修改：</p><pre class="crayon-plain-tag">@Override
    protected void onCreate(Bundle savedInstanceState) {
        .......
        //设置RecyclerView的布局管理
        mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
    }</pre><p>来到app\src\main\AndroidManifest.xml，添加StaggeredGridLayoutActivity</p><pre class="crayon-plain-tag">&lt;activity android:name=".StaggeredGridLayoutActivity"&gt;&lt;/activity&gt;</pre><p>最后，回到MainActivity.java，我们要在menu中打开StaggeredGridLayoutActivity：</p><pre class="crayon-plain-tag">public boolean onOptionsItemSelected(MenuItem item){
            .........
            case R.id.action_staggered:
                Toast.makeText(this,"You Clicked Staggered",Toast.LENGTH_SHORT).show();
                Intent intent=new Intent(this,StaggeredGridLayoutActivity.class);
                startActivity(intent);
                break;
             ..........
        }
        return true;
    }</pre><p>并且res\layout\item_single_textview.xml代码如下：</p><pre class="crayon-plain-tag">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:background="#44ff0000"
    android:layout_margin="3dp"
    android:layout_height="72dp"
    &gt;
    &lt;TextView
        android:id="@+id/id_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
         /&gt;
&lt;/FrameLayout&gt;</pre><p><img class="alignnone size-full wp-image-126" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2017/01/20170106213816.png" alt="20170106213816" width="351" height="601" /></p>
<p>好了，瀑布流效果已经展现。</p>
<p>我现在要展示出StaggeredGridLayoutActivity，和StaggeredAdapter的全部代码，以便大家参考：</p><pre class="crayon-plain-tag">public class StaggeredAdapter extends RecyclerView.Adapter&lt;StaggeredAdapter.MyViewHolder&gt; {

    private LayoutInflater mInflater;
    //上下文
    private Context mContext;
    private List&lt;String&gt; mDatas;

    //声明存放随机高度
    private List&lt;Integer&gt; mHeights;

    public StaggeredAdapter(Context context, List&lt;String&gt; datas){
        this.mContext=context;
        this.mDatas=datas;
        //载入布局页面
        mInflater=LayoutInflater.from(context);

        //创建随机高度
        mHeights=new ArrayList&lt;Integer&gt;();
        for(int i=0; i &lt; mDatas.size();i++){
            mHeights.add((int)(100+Math.random()*300));
        }
    }
    //创建ViewHolder
    @Override
    public StaggeredAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        /*
        inflate()的作用就是将一个用xml定义的布局文件查找出来，注意与findViewById()的区别，inflate是加载一个布局文件，而findViewById则是从布局文件中查找一个控件。
        关于LayoutInflater类inflate(int resource, ViewGroup root, boolean attachToRoot)方法三个参数的含义

        resource：需要加载布局文件的id，意思是需要将这个布局文件中加载到Activity中来操作。

        root：需要附加到resource资源文件的根控件，什么意思呢，就是inflate()会返回一个View对象，如果第三个参数attachToRoot为true，
        就将这个root作为根对象返回，否则仅仅将这个root对象的LayoutParams属性附加到resource对象的根布局对象上，
        也就是布局文件resource的最外层的View上，比如是一个LinearLayout或者其它的Layout对象。

        attachToRoot：是否将root附加到布局文件的根视图上
         */
        View view=mInflater.inflate(R.layout.item_single_textview,parent,false);
        MyViewHolder viewHolder = new MyViewHolder(view);
        return viewHolder;
    }
    //绑定ViewHolder
    @Override
    public void onBindViewHolder(StaggeredAdapter.MyViewHolder holder, int position) {
        ViewGroup.LayoutParams lp=holder.itemView.getLayoutParams();
        lp.height=mHeights.get(position);
        holder.itemView.setLayoutParams(lp);

        holder.tv.setText(mDatas.get(position));

    }
    //获取item数
    @Override
    public int getItemCount() {
        return this.mDatas.size();
    }


    class MyViewHolder extends ViewHolder {

        TextView tv;

        public MyViewHolder(View itemView) {
            super(itemView);
            tv= (TextView) itemView.findViewById(R.id.id_tv);
        }
    }
}</pre><p>&nbsp;</p><pre class="crayon-plain-tag">public class StaggeredGridLayoutActivity extends AppCompatActivity {

    //相关声明
    private RecyclerView mRecyclerView;
    private List&lt;String&gt; mDatas;
    private StaggeredAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //加载数据
        initDatas();
        //初始化Views
        initViews();

        mAdapter=new StaggeredAdapter(this,mDatas);
        mRecyclerView.setAdapter(mAdapter);
        //设置RecyclerView的布局管理
        mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
    }

    private void initViews() {
        mRecyclerView=(RecyclerView) findViewById(R.id.id_recyclerview);
    }

    private void initDatas() {
        mDatas = new ArrayList&lt;String&gt;();

        //A-z的所有字母
        for(int i='A'; i&lt;='z';i++){
            mDatas.add(""+(char)i);
        }
    }
}</pre><p>&nbsp;</p>
<h2>RecyclerView的添加和删除动画效果</h2>
<p>来到menu/main.xml下添加如下两个item：</p><pre class="crayon-plain-tag">&lt;item
        android:id="@+id/action_add"
        android:orderInCategory="100"
        android:title="add"
        android:showAsAction="ifRoom"
        /&gt;
    &lt;item
        android:id="@+id/action_delete"
        android:orderInCategory="100"
        android:title="delete"
        android:showAsAction="ifRoom"
        /&gt;</pre><p>app:showAsAction</p>
<p>1.always:这个值会使菜单项一直显示在ActionBar上。</p>
<p>2.ifRoom:如果有足够的空间,这个值会使菜单显示在ActionBar上。</p>
<p>3.never:这个值菜单永远不会出现在ActionBar是。</p>
<p>4.withText:这个值使菜单和它的图标，菜单文本一起显示。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>来到MainActivity，添加两个按钮的触发效果：</p><pre class="crayon-plain-tag">public boolean onOptionsItemSelected(MenuItem item){
        //通过调用item.getItemId()来判断菜单项
        switch (item.getItemId()){
            case R.id.action_add:
                Toast.makeText(this,"You Clicked add",Toast.LENGTH_SHORT).show();

                break;
            case R.id.action_delete:
                Toast.makeText(this,"You Clicked add",Toast.LENGTH_SHORT).show();
                
                break;</pre><p>还记得最最前面介绍的setItemAnimator吗？现在就要用到了,这可是动画效果的关键：</p><pre class="crayon-plain-tag">@Override
    protected void onCreate(Bundle savedInstanceState) {
        .........
        //设置RecyclerView的布局管理
        LinearLayoutManager linearLayoutMangaer= new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
        mRecyclerView.setLayoutManager(linearLayoutMangaer);

        mRecyclerView.setItemAnimator(new DefaultItemAnimator());</pre><p>动画还不行，当我们点击add和delete时，要有数据变化，所以还需要对SimpleAdapter进行处理，让其完成对数据的添加：</p><pre class="crayon-plain-tag">public class SimpleAdapter extends RecyclerView.Adapter&lt;MyViewHolder&gt; {

    public void addData(int pos){
        mDatas.add(pos,"Insert one");
        //这里不要调用 notifyDataSetChanged();因为没有动画效果
        notifyItemInserted(pos);
    }

    public void deleteData(int pos){
        mDatas.remove(pos);
        notifyItemRemoved(pos);
    }</pre><p>继续切换到MainActivity，来完成剩下的事情：</p><pre class="crayon-plain-tag">public boolean onOptionsItemSelected(MenuItem item){
        //通过调用item.getItemId()来判断菜单项
        switch (item.getItemId()){
            case R.id.action_add:
                Toast.makeText(this,"You Clicked add",Toast.LENGTH_SHORT).show();
                mAdapter.addData(1);
                break;
            case R.id.action_delete:
                Toast.makeText(this,"You Clicked add",Toast.LENGTH_SHORT).show();
                mAdapter.deleteData(1);
                break;</pre><p>你会注意到添加了：mAdapter.addData(1);mAdapter.deleteData(1);</p>
<p><img class="alignnone size-full wp-image-128" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2017/01/20170106221316.png" alt="20170106221316" width="304" height="522" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2> Item的onClick事件</h2>
<p>RecyclerView中并没有实现任何的onClick事件，所以这些都需要我们自己来实现：</p>
<p>切换到SimpleAdapter</p><pre class="crayon-plain-tag">public class SimpleAdapter extends RecyclerView.Adapter&lt;MyViewHolder&gt; {
    .........
    public interface OnItemClickListener
    {
        void onItemClick(View view,int position);
        void onItemLongClick(View view,int position);
    }
    private OnItemClickListener mOnItemClickListener;
    public void setOnItemClickListener(OnItemClickListener listener){
        this.mOnItemClickListener = listener;
    }</pre><p>接下来</p><pre class="crayon-plain-tag">//绑定ViewHolder
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.tv.setText(mDatas.get(position));

       
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });</pre><p>接下来</p><pre class="crayon-plain-tag">//绑定ViewHolder
    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        holder.tv.setText(mDatas.get(position));

        if(mOnItemClickListener!=null){
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                        mOnItemClickListener.onItemClick(holder.itemView,position);
                }
            });

            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    mOnItemClickListener.onItemLongClick(holder.itemView,position);
                    return false;
                }
            });
        }
      

    }</pre><p>MainAcivity使用：</p><pre class="crayon-plain-tag">@Override
    protected void onCreate(Bundle savedInstanceState) {
        ........
            mAdapter.setOnItemClickListener(new SimpleAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this,"click :"+position,Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onItemLongClick(View view, int position) {
                Toast.makeText(MainActivity.this,"long click:"+position,Toast.LENGTH_SHORT).show();
            }
        });</pre><p>&nbsp;</p>
<h2> 有一个很重要的Bug</h2>
<p>当我们点击ActionBar的add后，添加多个item，你会发现这多个item点击的onclick事件输出的position都是一样的，这可麻烦了，因为我们在实战中会经常用到这个position，怎么解决呢？从布局来看，这个item已经被插入进去了，并且item的位置也发生了变化。</p>
<p>我们来到SimpleAdapter，我们的position应该用holder.getLayoutPosition();来代替</p><pre class="crayon-plain-tag">@Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        holder.tv.setText(mDatas.get(position));

        //item点击
        if(mOnItemClickListener!=null){
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                  int layoutPosition =  holder.getLayoutPosition();
                        mOnItemClickListener.onItemClick(holder.itemView,layoutPosition);
                }
            });

            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    int layoutPosition =  holder.getLayoutPosition();
                    mOnItemClickListener.onItemLongClick(holder.itemView,layoutPosition);
                    return false;
                }
            });
        }
        //end item点击

    }</pre><p><img class="alignnone size-full wp-image-132" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2017/01/20170106231319.png" alt="20170106231319" width="306" height="526" /></p>
<p>万事大吉，希望你在实战中，展现更好的效果！</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>本文主要是：http://www.imooc.com/learn/424     明日之星-RecyclerView的记录</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/118">android之RecyclerView</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/mobile/archives/118/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android之Retrofit的使用</title>
		<link>http://www.newlifeclan.com/mobile/archives/55</link>
		<comments>http://www.newlifeclan.com/mobile/archives/55#comments</comments>
		<pubDate>Sat, 23 Jul 2016 04:11:05 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[Android开发]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/mobile/?p=55</guid>
		<description><![CDATA[<p>使用Retrofit（这是一个极其棒的网络请求库）来制作一个访问雅虎天气的demo。一步一步看看Retrofi [&#8230;]</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/55">Android之Retrofit的使用</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>使用Retrofit（这是一个极其棒的网络请求库）来制作一个访问雅虎天气的demo。一步一步看看Retrofit是如何完成的。</p>
<p><span id="more-55"></span></p>
<h2>yahoo 天气 json</h2>
<p>首先我们来到这个链接（https://developer.yahoo.com/weather/），改写需要查询的地点为北京</p>
<p><img class="alignnone size-full wp-image-57" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2016/07/20160721094902.png" alt="20160721094902" width="668" height="500" /></p>
<p>根据这张图，你可以看到yahoo给我返回的json和访问这个json的api链接。</p>
<p>还要小调整一下，默认你会看到返回的json中 &#8220;temperature&#8221;: &#8220;F&#8221; ，我们需要把他改成 &#8220;temperature&#8221;: &#8220;C&#8221;（摄氏温度）,要在原来的YQL中加入（ and u=&#8217;c&#8217;）</p><pre class="crayon-plain-tag">select * from weather.forecast where woeid in (select woeid from geo.places(1) where text="beijing") and u='c'</pre><p>&nbsp;</p>
<p>&nbsp;</p>
<h2>安装Retrofit库</h2>
<p>Retrofit是一个不错的网络请求库，而且用起来很省事。</p>
<p>打开https://github.com/square/retrofit ，你会看到它的详细信息，包括一个官网http://square.github.io/retrofit/。</p>
<p>使用Gradle方式安装它：</p><pre class="crayon-plain-tag">compile 'com.squareup.retrofit2:retrofit:2.1.0'</pre><p>把上面的代码附加到（build.gradle(Module.app)）：</p><pre class="crayon-plain-tag">dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
}</pre><p>然后，点击 android studio 右上角的 sync now 进行安装</p>
<p><img class="alignnone size-full wp-image-60" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2016/07/20160721101843.png" alt="20160721101843" width="827" height="26" /></p>
<p>还没完，来到http://square.github.io/retrofit/。我们还需要使用到<a href="https://github.com/google/gson">Gson</a>，所以我们还要安装它才行，加入：</p><pre class="crayon-plain-tag">compile 'com.squareup.retrofit2:converter-gson:2.1.0'</pre><p>ok。</p>
<p>&nbsp;</p>
<h2>jsonschema2pojo</h2>
<p>这个小工具是用来将JOSN转换成普通的java对象类。我们可以把我们之前生成的json放入到里面去，来创建我们需要的java对象。</p>
<p>打开这个工具的网址：http://www.jsonschema2pojo.org/</p>
<p><img class="alignnone size-full wp-image-62" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2016/07/20160721154144.png" alt="20160721154144" width="809" height="735" /></p>
<p>区域1：填写你之前【yahoo天气json】获取的json数据</p>
<p>Package：com.example.napoleon.myapplication.data 这是我们要放置的包名</p>
<p>Class name：Weather  我们需要创建的类名</p>
<p>点击：Preview可以预览要生成的Model类，Zip可以生成并下载这些类。</p>
<p>如果下载完毕，我们把相关的类，copy到我们的项目中去：</p>
<p><img class="alignnone size-full wp-image-63" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2016/07/20160721163757.png" alt="20160721163757" width="357" height="443" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>但是你copy这些文件后，他们有错误：</p><pre class="crayon-plain-tag">import javax.annotation.Generated;

@Generated("org.jsonschema2pojo")</pre><p>怎么处理呢？</p>
<p>我们需要在build.gradle中添加</p><pre class="crayon-plain-tag">compile 'org.glassfish:javax.annotation:10.0-b28'</pre><p>如下位置</p><pre class="crayon-plain-tag">dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'

    compile 'org.glassfish:javax.annotation:10.0-b28'
}</pre><p>安装后，就不会报错了。</p>
<p>&nbsp;</p>
<h2>创建WeatherAPI</h2>
<p>来到项目中，创建remote包，并创建WeatherAPI接口，来让你的HTTP API转换成a Java interface，粘贴<strong>Retrofit</strong>官网前几步到你的文件中：</p><pre class="crayon-plain-tag">package com.example.napoleon.myapplication.remote;


public interface WeatherAPI {

    @GET("users/{user}/repos")
    Call&lt;List&lt;Repo&gt;&gt; listRepos(@Path("user") String user);


    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .build();

    GitHubService service = retrofit.create(GitHubService.class);
}</pre><p></p>
<blockquote><p> Retrofit可以将你的HTTP API转化为JAVA的接口的形式。例如：</p><pre class="crayon-plain-tag">public interface GitHubService {
  @GET("users/{user}/repos")
  Call&lt;List&lt;Repo&gt;&gt; listRepos(@Path("user") String user);
}</pre><p>而Retrofit类能够生成对应接口的实现。例如：</p><pre class="crayon-plain-tag">Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);</pre><p>每一个由接口返回的Call对象都可以与远程web服务端进行同步或者异步的HTTP请求通信。例如：</p><pre class="crayon-plain-tag">Call&lt;List&lt;Repo&gt;&gt; repos = service.listRepos("octocat");</pre><p>Retrofit使用注解来描述HTTP请求：<br />
1.URL参数的替换和query参数的支持<br />
2.对象转化为请求体（如：JSON，protocol buffers等）<br />
3.多重请求体和文件上传<br />
注意：本站仍在为2.0扩展新的API</p></blockquote>
<p>&nbsp;</p>
<p>好了，我们要根据我们之前获取json的url，分析来改写这个类：</p><pre class="crayon-plain-tag">package com.example.napoleon.myapplication.remote;


import com.example.napoleon.myapplication.data.Weather;

import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.http.GET;
import retrofit2.http.Path;

public interface WeatherAPI {

    String BASE_UEL="https://query.yahooapis.com/v1/public/";

    @GET("yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22beijing%22)%20and%20u%3D'c'&amp;format=json&amp;env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")
    Call&lt;Weather&gt; getWeather();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_UEL)
            .build();

    WeatherAPI service = retrofit.create(WeatherAPI.class);
}</pre><p>具体可查看http://square.github.io/retrofit/</p>
<p>还没完你知道这样是不行的，我们还要进一步优化：</p><pre class="crayon-plain-tag">package com.example.napoleon.myapplication.remote;


import com.example.napoleon.myapplication.data.Weather;

import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.http.GET;

public interface WeatherAPI {

    String BASE_UEL="https://query.yahooapis.com/v1/public/";

    @GET("yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22beijing%22)%20and%20u%3D'c'&amp;format=json&amp;env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")
    Call&lt;Weather&gt; getWeather();

    class Factory{

        private static WeatherAPI service;

         public static WeatherAPI getIstance(){
             if(service == null){
                 Retrofit retrofit = new Retrofit.Builder()
                         .addConverterFactory(GsonConverterFactory.create())
                         .baseUrl(BASE_UEL)
                         .build();

                 service = retrofit.create(WeatherAPI.class);
                 return service;
             }else {
                return service;
             }

         }
    }
}</pre><p>上面方便我们日后的使用，并且做了一个判断，当我们有WeatherAPI时，我们无需再生成对应的接口了。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>构建视图</h2>
<p>视图的布局和组件代码如下：</p><pre class="crayon-plain-tag">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.napoleon.myapplication.MainActivity"&gt;


    &lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/textView_city"
        android:textSize="65px"
        /&gt;

    &lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/textView_conditions"
        android:layout_below="@+id/textView_city"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" /&gt;

    &lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/textView_temperature"
        android:textSize="120px"
        android:layout_above="@+id/textView_lastupdated"
        android:layout_centerHorizontal="true" /&gt;

    &lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/textView_lastupdated"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/textView_city"
        android:layout_toEndOf="@+id/textView_city" /&gt;

    &lt;Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="刷新"
        android:id="@+id/button_refresh"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" /&gt;
&lt;/RelativeLayout&gt;</pre><p>下面是WeatherActivity的代码：</p>
<p>&nbsp;</p><pre class="crayon-plain-tag">package com.example.napoleon.myapplication;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;

public class WeatherActivity extends AppCompatActivity {
    @BindView(R.id.textView_city) TextView textView_city;
    @BindView(R.id.textView_conditions) TextView textView_conditions;
    @BindView(R.id.textView_temperature) TextView textView_temperature;
    @BindView(R.id.textView_lastupdated) TextView textView_lastupdated;
    @BindView(R.id.button_refresh) TextView button_refresh;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_weather);
        ButterKnife.bind(this);
    }
}</pre><p>我们使用了一个<a href="http://jakewharton.github.io/butterknife/" target="_blank">ButterKnife插件</a>，他的安装也很简单。</p>
<p>需要在（Project:MyApplication)的build.gradle中加入classpath &#8216;com.neenbedankt.gradle.plugins:android-apt:1.8&#8217;：</p><pre class="crayon-plain-tag">buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.2'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}</pre><p>GRADLE：</p><pre class="crayon-plain-tag">apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
....
compile 'com.jakewharton:butterknife:8.2.1'
apt 'com.jakewharton:butterknife-compiler:8.2.1'</pre><p>再往Android Studio上安装该插件</p>
<p><img class="alignnone size-large wp-image-66" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2016/07/androidstudiobutterknife-1024x490.png" alt="androidstudiobutterknife" width="780" height="373" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2> 绑定数据</h2>
<p>程序需要点击刷新按钮，然后显示相应的天气信息，我们现在需要一个OnClick事件：</p><pre class="crayon-plain-tag">@OnClick(R.id.button_refresh)
    public void onClick_botton_refresh(){
        WeatherAPI.Factory.getIstance().getWeather().enqueue(new Callback&lt;Weather&gt;() {
            @Override
            public void onResponse(Call&lt;Weather&gt; call, Response&lt;Weather&gt; response) {

            }

            @Override
            public void onFailure(Call&lt;Weather&gt; call, Throwable t) {

            }
        });
    }</pre><p>然后将数据绑定到各个控件上：</p><pre class="crayon-plain-tag">@OnClick(R.id.button_refresh)
    public void onClick_botton_refresh(){
        WeatherAPI.Factory.getIstance().getWeather().enqueue(new Callback&lt;Weather&gt;() {
            @Override
            public void onResponse(Call&lt;Weather&gt; call, Response&lt;Weather&gt; response) {
                Query query = response.body().getQuery();
                textView_temperature.setText(query.getResults().getChannel().getItem().getCondition().getTemp());
                textView_city.setText(query.getResults().getChannel().getLocation().getCity());
                textView_lastupdated.setText(query.getResults().getChannel().getLastBuildDate());
                textView_conditions.setText(query.getResults().getChannel().getItem().getCondition().getText());
            }

            @Override
            public void onFailure(Call&lt;Weather&gt; call, Throwable t) {
                     Log.e("Failed",t.getMessage());
            }
        });
    }


    @Override
    protected void onResume(){
        super.onResume();
        onClick_botton_refresh();
    }</pre><p>还需要将这个类设置为启动页，来到AndroidManifest.xml文件，改写为WeatherActivity</p><pre class="crayon-plain-tag">&lt;activity android:name=".WeatherActivity"&gt;
            &lt;intent-filter&gt;
                &lt;action android:name="android.intent.action.MAIN" /&gt;

                &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;</pre><p>当然别忘了加入访问网络的权限</p><pre class="crayon-plain-tag">&lt;uses-permission android:name="android.permission.INTERNET"&gt;&lt;/uses-permission&gt;</pre><p>如果你使用Genymotion一定要注意虚拟机也要联网哦。如果用的是wifi那么虚拟机也要连接wifi的。</p>
<p>&nbsp;</p>
<p>看看效果：</p>
<p><img class="alignnone size-large wp-image-74" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2016/07/20160723121152-592x1024.png" alt="20160723121152" width="592" height="1024" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/55">Android之Retrofit的使用</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/mobile/archives/55/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android ListView 一</title>
		<link>http://www.newlifeclan.com/mobile/archives/52</link>
		<comments>http://www.newlifeclan.com/mobile/archives/52#comments</comments>
		<pubDate>Sat, 16 Jul 2016 15:07:19 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[Android开发]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/mobile/?p=52</guid>
		<description><![CDATA[<p>android中listview是一个很常用的控件，他用列表的形式来展现内容。 我们使用Android stu [&#8230;]</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/52">Android ListView 一</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>android中listview是一个很常用的控件，他用列表的形式来展现内容。<span id="more-52"></span></p>
<p>我们使用Android studio 创建一个项目，在activity_main.xml中书写：</p><pre class="crayon-plain-tag">&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.napoleon.myapplication.MainActivity"&gt;


    &lt;ListView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/listView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" /&gt;

&lt;/RelativeLayout&gt;</pre><p>上面的代码我添加了一个listview.</p>
<p>下面我们需要给listview一个数据集合，让listview显示这些数据，我们如何绑定这些数据呢？那么就需要适配器和listview进行配合了。</p><pre class="crayon-plain-tag">import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {

    private ListView lv;

    //定义arrayadapte
    private ArrayAdapter&lt;String&gt; adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        
        adapter = new ArrayAdapter&lt;String&gt;(this,android.R.layout.simple_list_item_1);

        lv = (ListView) findViewById(R.id.listView);

        //设置数据适配器
        lv.setAdapter(adapter);

        adapter.add("hello");
        adapter.add("eoe");
    }
}</pre><p>上面定义了两个私有变量，listview和ArrayAdapter，分别代表一个listview控件和字符串泛型的数组适配器。在onCreate中绑定相应对象。</p><pre class="crayon-plain-tag">adapter = new ArrayAdapter&lt;String&gt;(this,android.R.layout.simple_list_item_1);</pre><p>这段话绑定了，android系统资源的列表项</p><pre class="crayon-plain-tag">lv.setAdapter(adapter);</pre><p>此句是让listview设置数据适配器</p><pre class="crayon-plain-tag">adapter.add("hello");</pre><p>这句就很好理解了，就是向适配器添加数据。</p>
<p>ok了，运行，我们的程序看看结果：</p>
<p><img class="alignnone size-full wp-image-53" src="http://www.newlifeclan.com/mobile/wp-content/uploads/sites/6/2016/07/20160716230539.png" alt="20160716230539" width="758" height="509" /></p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/mobile/archives/52">Android ListView 一</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/mobile">移动技术</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/mobile/archives/52/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
