这是“ 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,它管理由任意对象数组支持的ListView 。 ArrayAdapter将使用从原始活动中检索的电影列表进行初始化。 然后,我们使用setListAdapter方法将ListActivity与ArrayAdapter关联。
我们希望处理列表中每个项目的点击事件,更具体地说,是要在电影的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项目。
- “ Android完整应用程序教程”系列
- Android文字转语音应用
- 带有Yahoo API的Android反向地理编码– PlaceFinder
- Android基于位置的服务应用程序– GPS位置
- 使用VirtualBox在PC上安装Android OS
- 拥抱Android的强大功能:快速概述
翻译自: https://www.javacodegeeks.com/2010/11/android-full-app-part-5-launch-activity.html