Android Full App,第5部分:有意图地启动新活动

这是“ Android完整应用程序教程”系列的第五部分。 完整的应用程序旨在提供一种通过互联网搜索表演电影/演员的简便方法。 在本系列的第一部分( “主要活动UI” )中,我们创建了Eclipse项目并为应用程序的主要活动设置了基本界面。 在第二部分( “使用HTTP API” )中,我们使用Apache HTTP客户端库来使用外部HTTP API并将API的搜索功能集成到我们的应用程序中。 在第三部分( “解析XML响应” )中,我们看到了如何使用Android内置的XML解析功能来解析XML响应。 在第四部分( “从主要活动异步执行API请求” )中,我们将HTTP检索器和XML解析器服务绑定在一起,以便从应用程序的主要活动中执行API搜索请求。 为了避免阻塞主UI线程,该请求是在后台线程中异步执行的。 在这一部分中,我们将看到如何启动一个新的Activity以及如何将数据从一个Activity传输到另一个Activity

Google已发布了活动和任务设计指南 ,从高层,以用户为中心的角度描述了Android应用程序框架的核心原理,这对交互以及应用程序设计人员和应用程序开发人员很有用。 您应该看一下指南,但现在我们只需要在此处提及有关“活动”的几件事:

  • 活动是Android应用程序的主要构建块。
  • 当用户在用户界面中移动时,他们一个接一个地开始活动。
  • 每个活动的生命周期都独立于其应用程序或任务中的其他活动。
  • Android会保留用户访问过的活动(活动堆栈)的线性导航历史记录。
  • 可以使用Intent类在活动之间传输数据。

到目前为止,在我们的教程中,我们在主要活动中执行了电影搜索,并仅使用Toast将结果通知了用户。 现在,我们将更进一步,并使用一个新的活动,其中的结果将显示为列表。 因此,新活动实际上将扩展ListActivity Android类,这是一种特殊的活动,它通过绑定到数据源(例如数组或Cursor)来显示项目列表。

新的活动将通过Intent从主要活动中启动。 我们将使用涉及上下文和目标Intent构造函数 。 从参考文档中,我们了解到,此构造函数“提供了一种创建意图的意图,该意图旨在执行硬编码的类名,而不是依赖系统为您找到合适的类”。 因为我们知道我们要处理哪些活动意图 ,这是适合的。

为了在两个活动之间传输数据,我们将使用Intent类提供的重载putExtra方法之一。 可传输的数据必须是可序列化的,并且由于ArrayList是默认设置,因此我们还必须使用mark接口标记模型类(Movie / Person / Image)。 最后,我们使用startActivity方法启动已知的新活动。

因此,在“ PerformMovieSearchTask”类内部,我们使用以下代码来启动将处理搜索结果表示的新活动:

...
Intent intent = 
 new Intent(MovieSearchAppActivity.this, MoviesListActivity.class);
intent.putExtra("movies", result);
startActivity(intent);
...

不要忘记将模型类标记为可序列化的:

...
public class Movie implements Serializable
...
public class Person implements Serializable
...
public class Image implements Serializable
...

为了让系统找到新活动,我们必须在“ AndroidManifest.xml”文件中对其进行声明。 通过在“ application”元素内添加以下行,可以非常轻松地完成此操作:

...
<activity android:name=".MoviesListActivity" />
...

新的ListActivity将在其onCreate方法中检索数据。 为此,我们首先使用返回原始意图的getIntent方法来引用启动活动的意图。 然后,我们通过getSerializableExtra方法检索扩展的数据,在这里我们使用先前通过putExtra方法添加的项目的名称。 由于该方法返回一个Serializable对象,因此我们执行必要的强制转换。

为了将搜索结果显示在列表中,我们需要使用ArrayAdapter ,即ListAdapter,它管理由任意对象数组支持的ListViewArrayAdapter将使用从原始活动中检索的电影列表进行初始化。 然后,我们使用setListAdapter方法将ListActivityArrayAdapter关联。

我们希望处理列表中每个项目的点击事件,更具体地说,是要在电影的IMDB页面中打开浏览器。 因此,我们重写了onListItemClick方法,该方法在列表中的一个项目被选中时调用。 在该方法内部,我们使用ArrayAdapter检索与列表项关联的Movie对象,找到IMDB ID,然后构造IMDB页面URL,该URL由以下内容组成:

基本网址: http//m.imdb.com/title/

以及相应的电影ID。 然后,我们创建一个新的Intent,其操作设置为ACTION_VIEW 。 这是“活动操作”,通常向用户显示数据。 如果是URL,将启动默认浏览器并将其重定向到目标页面。 使用常规方法startActivity启动处理意图的新活动。

让我们看一下“ MoviesListActivity”类的代码:

package com.javacodegeeks.android.apps.moviesearchapp;

import java.util.ArrayList;

import android.app.ListActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.javacodegeeks.android.apps.moviesearchapp.model.Movie;

public class MoviesListActivity extends ListActivity {
    
    private static final String IMDB_BASE_URL = "http://m.imdb.com/title/";
    
    private ArrayList<Movie> moviesList;
    private ArrayAdapter<Movie> moviesAdapter;
    
    @SuppressWarnings("unchecked")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.movies_layout);
        
        moviesList = (ArrayList<Movie>) getIntent().getSerializableExtra("movies");
        
        moviesAdapter = new ArrayAdapter<Movie>(this, android.R.layout.simple_list_item_1, moviesList);
        
        setListAdapter(moviesAdapter);
        
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        
        super.onListItemClick(l, v, position, id);
        Movie movie = moviesAdapter.getItem(position);
        
        String imdbId = movie.imdbId;
        if (imdbId==null || imdbId.length()==0) {
            longToast(getString(R.string.no_imdb_id_found));
            return;
        }
        
        String imdbUrl = IMDB_BASE_URL + movie.imdbId;
        
        Intent imdbIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(imdbUrl));                
        startActivity(imdbIntent);
        
    }
    
    public void longToast(CharSequence message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }
    
}

注意, ArrayAdapter使用每个封装对象的toString方法,因此我们应该重写该方法并提供更有意义的表示形式:

@Override
public String toString() {
 StringBuilder builder = new StringBuilder();
 builder.append("Movie [name=");
 builder.append(name);
 builder.append("]");
 return builder.toString();
}

描述我们活动的内容视图的布局文件需要具有ID为“ @ + id / android:list”的ListView声明。 此外,我们提供了ID为“ @ + id / android:empty”的TextView ,该列表将在列表中不包含任何项目的情况下出现。 这些视图包含在LinearLayout内部,该布局是将其子级排列在单列或单行中的布局。 XML文件位于“ res / layout”文件夹中,名为“ movies_layout.xml”,其内容如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   >
   
 <ListView
     android:id="@+id/android:list"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     />
 <TextView
     android:id="@+id/android:empty"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:text="@string/no_movies_found"/>
    
</LinearLayout>

现在,运行Eclipse配置,提供查询字符串,执行电影搜索并等待直到检索到结果。

检索后,将调用“ MoviesListActivity”类,并将结果显示在列表中(如上所述,调用toString方法)。

您可以向下滚动(由Android自动处理),然后单击要查找其详细信息的电影。 这将触发一个事件,该事件将打开设备的浏览器并指向电影的IMDB页面:

大! 电影信息直接发送到我们的智能手机! 您可以在此处下载到目前为止创建的Eclipse项目。

相关文章 :

翻译自: https://www.javacodegeeks.com/2010/11/android-full-app-part-5-launch-activity.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值