博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面试:谈谈redis_让我们来谈谈:PHP和Android的高效通信,第1部分
阅读量:2506 次
发布时间:2019-05-11

本文共 12924 字,大约阅读时间需要 43 分钟。

面试:谈谈redis

The mobile space has exploded in the last several years, prompting the realization that service-oriented architecture is a great way to implement business logic for consumption by both web and mobile applications. While mobile devices have evolved dramatically, their increased availability to consumers has added strain on networks and service providers who are still struggling to make capacity meet demand. To keep hardware costs down, developers must now pinch bytes of bandwidth just as they did with memory back in the early days of computing.

在过去的几年中,移动领域迅猛发展,这促使人们意识到面向服务的体系结构是一种实现业务逻辑以供Web和移动应用程序使用的好方法。 尽管移动设备已经发生了巨大的发展,但它们向消费者提供的增加的可用性给仍在努力使容量满足需求的网络和服务提供商增加了压力。 为了降低硬件成本,开发人员现在必须像在早期计算内存时那样,缩小带宽字节。

This two-part article will guide you through the process of building an efficient PHP-based REST web service to be consumed by an Android-based application. Some of the concepts presented here are also applicable to other mobile platforms, such as iOS. I assume you already know the basics of PHP and Android development and that you have a suitable development environments set up for both. I’ll focus mainly on showing you how to handle data serialization and compression in both environments.

这篇分为两部分的文章将指导您完成构建有效的基于PHP的REST Web服务的过程,以供基于Android的应用程序使用。 此处介绍的某些概念也适用于其他移动平台,例如iOS。 我假设您已经了解PHP和Android开发的基础知识,并且已经为两者设置了合适的开发环境。 我将重点介绍如何在两种环境中处理数据序列化和压缩。

共同要求 (A Common Request)

Here are the particular parts of a typical HTTP operation that we’re interested in:

以下是我们感兴趣的典型HTTP操作的特定部分:

  1. The client (e.g. the Android application) sends an HTTP request to the REST service (e.g. the server) and uses request headers to indicate which data serialization and compression formats it supports.

    客户端(例如Android应用程序)将HTTP请求发送到REST服务(例如服务器),并使用请求标头指示其支持的数据序列化和压缩格式。
  2. Based on the request headers, the server determines which data serialization and compression formats it has in common with the client, selects one of each, applies them to the requested data, and sends a response containing headers specifying its selections and the data back to the client.

    服务器根据请求标头确定与客户端共有的数据序列化和压缩格式,选择其中一种,将其应用于请求的数据,然后将包含标头的响应(指定其选择内容和数据)发送给客户端。客户。
  3. Based on the response headers, the client applies the corresponding decompression and deserialization routines to the data to restore it to its original state and can then use it for its intended purpose.

    客户端根据响应标头对数据应用相应的解压缩和反序列化例程,以将其恢复为原始状态,然后可以将其用于预期的目的。

Let’s start at the beginning and go through each step.

让我们从头开始,并完成每个步骤。

索取资料 (Requesting Data)

In order to make HTTP requests, your Android application to access the Internet. You need to declare this in your project’s AndroidManifest.xml file like so:

为了发出HTTP请求,您的Android应用程序访问Internet的 。 您需要像这样在项目的AndroidManifest.xml文件中声明此代码:

Afterwards, you need a class that actually handles making the HTTP requests and processing the responses. For this I will use the native AndroidHttpClient class which comes with a default configuration suitable for most purposes including use of a thread-safe connection manager.

然后,您需要一个类来实际处理发出HTTP请求和处理响应的类。 为此,我将使用原生的AndroidHttpClient类,该类具有适合大多数目的的默认配置,包括使用线程安全的连接管理器。

The AndroidHttpClient class is only available in Android 2.2 (API level 8) and above. To support , look at the class from the that Android has included since its first version.

AndroidHttpClient类仅在Android 2.2(API级别8)及更高版本中可用。 要支持 ,请查看Android自第一个版本以来就包含的中的类。

import android.net.http.AndroidHttpClient;import java.io.IOException;import org.apache.http.HttpResponse;import org.apache.http.client.methods.HttpGet;public class DataModel {    protected AndroidHttpClient httpClient;    protected HttpGet httpRequest;    public DataModel() {        this.httpClient = AndroidHttpClient.newInstance(            "Android " + android.os.Build.VERSION.RELEASE            // Your app name would also be an acceptable value here        );    }    public DataValueObject getData() throws IOException {        HttpGet httpRequest = new HttpGet(            "http://10.0.2.2/php-android/");        httpRequest.addHeader("Accept",             "application/json;q=1,application/x-msgpack;q=0.9");        httpRequest.addHeader("Accept-Encoding",             "bzip2,gzip,deflate");        HttpResponse httpResponse = this.httpClient.execute(httpRequest);        // ...    }}

When this class is instantiated, it internally creates an instance of AndroidHttpClient. When the getData() method is called to request data, it creates an , populates it with request data, and uses the AndroidHttpClient instance to send it. Included in the request data are the following:

实例化此类时,它将在内部创建一个AndroidHttpClient实例。 当getData()方法被调用来请求数据,它创建了一个 ,与请求数据填充它,并使用AndroidHttpClient实例来发送它。 请求数据中包括以下内容:

  1. The URL of the resource being requested (i.e. your REST endpoint). If you host this on the same machine hosting your Android development environment, you can access it from the emulator using the IP address 10.0.2.2 (as in the above example) and from a physical device plugged in via USB using the IP address 10.0.1.2.

    被请求资源的URL(即您的REST端点)。 如果将其托管在托管Android开发环境的同一台计算机上,则可以使用IP地址10.0.2.2从仿真器中进行访问(如上例所示),也可以使用IP地址10.0通过USB通过物理设备进行访问。 1.2。
  2. The data serialization formats supported by the client, in this case and , and their respective quality factors, floating point numbers between 0 and 1 with higher numbers indicating a higher preference for that particular format. More information on these can be found in

    客户端支持的数据序列化格式(在本例中为和 ,以及它们各自的质量因数,即介于0和1之间的浮点数,其中较高的数字表示对该特定格式的更高的偏爱。 有关这些的更多信息,请参见

  3. The data encoding formats supported by the client, in this case , , and . More information on these can be found in .

    客户端支持的数据编码格式,在本例中为 , 和 。 有关这些的更多信息,请参见 。

  4. It’s possible for the AndroidHttpClient instance to encounter issues, such as the server not being available. Its execute() method can throw an IOException to indicate this, which the code calling getData() can catch and handle as appropriate.

    AndroidHttpClient实例可能会遇到问题,例如服务器不可用。 它的execute()方法可以抛出IOException来表明这一点,调用getData()的代码可以适当地捕获和处理该IOException

    We’ll come back to the rest of the getData() method in a later section when we examine processing the response, but for now we need to implement use of this class in an .

    在后面的部分中,当我们检查处理响应时,我们将返回到getData()方法的其余部分,但是现在我们需要在实现此类的使用。

    实施后台任务 (Implementing a Background Task)

    Requesting and processing data in the context of a mobile application is an asynchronous operation. That is, we want the application to send the request for the data and then take some action once the response is received, such as populating the user interface with the data.

    在移动应用程序上下文中请求和处理数据是异步操作。 也就是说,我们希望应用程序发送对数据的请求,然后在收到响应后采取一些措施,例如用数据填充用户界面。

    By default, Android in its own and , the latter of which is often called the UI thread because user interface operations run on it. As such, intensive operations like obtaining and processing data from a web service should be run on a separate thread so as not to block UI operations, which generally results in irritated users. To do this, we need to write a subclass of to encapsulate the process.

    默认情况下,Android在其各自的和 ,后者通常称为UI线程,因为用户界面操作在其上运行。 这样,诸如从Web服务获取和处理数据之类的密集操作应在单独的线程上运行,以免阻塞UI操作,这通常会激怒用户。 为此,我们需要编写的子类来封装该过程。

    import java.io.IOException;import android.app.Activity;import android.app.AlertDialog;import android.app.ProgressDialog;import android.content.DialogInterface;import android.os.AsyncTask;public class GetDataTask extends AsyncTask
    { ProgressDialog progressDialog; Activity activity; String error; public GetDataTask(Activity activity) { super(); this.activity = activity; } protected String getString(int id) { return this.activity.getResources().getString(id); } @Override protected void onPreExecute() { progressDialog = ProgressDialog.show( this.activity, "", getString(R.string.loading), true, false ); } @Override protected DataValueObject doInBackground(Void... params) { DataModel dataModel = new DataModel(); DataValueObject dvo = null; try { dvo = dataModel.getData(); } catch (IOException e) { this.error = getString(R.string.error); // or e.getMessage() when debugging } return dvo; } @Override protected void onPostExecute(DataValueObject dvo) { if (dvo != null) { // Do something useful with dvo here // Dismiss the progress dialog when done progressDialog.dismiss(); } else { // Dismiss the progress dialog progressDialog.dismiss(); // Display a simple error dialog to the user new AlertDialog.Builder(this.activity) .setMessage(this.error) .setNeutralButton( getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } } ) .create() .show(); } }}

    As part of extending AsyncTask, this class specifies that the result of the operation will be an instance of the DataValueObject class which the getData() method of the DataModel class returns. The class constructor takes as its only parameter the activity instance that’s invoking it. This is used later to access localized strings and use the activity in other context-specific tasks.

    作为扩展AsyncTask一部分,此类指定操作的结果将是DataValueObject类的实例,该实例由DataModel类的getData()方法返回。 类构造函数将调用它的活动实例作为其唯一参数。 以后将使用它来访问本地化的字符串,并在其他特定于上下文的任务中使用活动。

    The onPreExecute() and onPostExecute() methods will vary depending on what you want to do before and after the background operation starts. My examples above show a simple use case of displaying a progress dialog and potentially an alert dialog when an error occurs.

    onPreExecute()onPostExecute()方法会有所不同,具体取决于您要在后台操作开始之前和之后执行的操作。 我上面的示例显示了一个简单的用例,当出现错误时,将显示进度对话框,并可能显示警报对话框。

    doInBackground() contains the logic that needs to run in a background thread, in this case calling getData(). It returns an instance of DataValueObject or null if an error occurs. That value is then passed to onPostExecute() when it’s invoked so you can do something useful with it.

    doInBackground()包含需要在后台线程中运行的逻辑,在本例中,该逻辑调用getData() 。 它返回DataValueObject的实例;如果发生错误,则返回null。 然后在调用该值时将其传递给onPostExecute() ,以便您可以执行一些有用的操作。

    执行后台任务 (Executing the Background Task)

    Now that we’ve properly encapsulated the background task we want to run to fetch the data, we need to actually invoke it in an activity. Part of this will require checking that a network connection is available so that the request for data can actually get to the server. Doing this requires adding an additional permission to your AndroidManifest.xml file:

    现在,我们已经正确封装了要运行的后台任务以获取数据,我们需要在活动中实际调用它。 其中一部分将需要检查网络连接是否可用,以便对数据的请求实际上可以到达服务器。 为此,需要向您的AndroidManifest.xml文件添加其他权限:

    An activity class that kicks off the background task when the activity is created might look like this:

    创建活动时启动后台任务的活动类可能如下所示:

    import android.app.Activity;import android.content.Context;import android.net.ConnectivityManager;import android.net.NetworkInfo;import android.os.Bundle;public class MyActivity extends Activity {    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        if (networkIsAvailable()) {            new GetDataTask(this).execute();        } else {            // Display an error to the user about network unavailability        }    }    public boolean networkIsAvailable() {        ConnectivityManager cm = (ConnectivityManager)             getSystemService(Context.CONNECTIVITY_SERVICE);        NetworkInfo networkInfo = cm.getActiveNetworkInfo();        return networkInfo != null && networkInfo.isConnected();    }}

    The networkIsAvailable() method simply queries the appropriate service to determine if a network connection is available. If your application has a base activity class, this may be a useful method to include in it. The onCreate() activity hook uses networkIsAvailable() to either execute the background task or display an appropriate error message to the user. Executing the task is simply a matter of instantiating it with a reference to the activity and calling its execute() method.

    networkIsAvailable()方法只是查询适当的服务以确定网络连接是否可用。 如果您的应用程序具有基本活动类,则这可能是一个有用的方法。 onCreate()活动挂钩使用networkIsAvailable()执行后台任务或向用户显示适当的错误消息。 执行任务只是通过引用活动实例化它并调用其execute()方法即可。

    下次 (Next Time)

    Part 1 of this article has focused mainly on setting up the Android application to make the request. In part 2 of this article coming up, we’ll get into the meat of handling data serialization and compression in both environments. Stay tuned!

    本文的第1部分主要关注于设置Android应用程序以发出请求。 在本文的第2部分中,我们将深入探讨在两种环境中处理数据序列化和压缩的问题。 敬请关注!

    Image via

    图片来自

翻译自:

面试:谈谈redis

转载地址:http://fqrgb.baihongyu.com/

你可能感兴趣的文章
(动态规划、递归) leetcode 87. Scramble String
查看>>
[补档]暑假集训D8总结
查看>>
Linux如何查看JDK的安装路径
查看>>
git命令-切换分支
查看>>
jquery 事件冒泡的介绍以及如何阻止事件冒泡
查看>>
11月2号 assertj断言
查看>>
Oracle与MySQL的比较[内容来自网络]
查看>>
如何使用chrome浏览器进行js调试找出元素绑定的点击事件
查看>>
JDBC中的PreparedStatement
查看>>
java中接口和抽象类的区别
查看>>
模板方法模式--TemplateMethod
查看>>
split a string in C++
查看>>
intent
查看>>
iOS 为工程创建pch文件
查看>>
H5各种头部meta标签功能大全
查看>>
6.博客系统| 点赞功能
查看>>
swift中Cell的内容定制
查看>>
求解有向图最小平均值环(minimum mean-weight cycle)
查看>>
sklearn交叉验证3-【老鱼学sklearn】
查看>>
正则表达式RegExp详解(待续)
查看>>