我熟悉Android框架和Java,并希望创建一个通用的“NetworkHelper”类,它可以处理大多数网络代码,使我能够从中调用网页 .
我在developer.android.com上关注这篇文章来创建我的网络类:http://developer.android.com/training/basics/network-ops/connecting.html
码:
package com.example.androidapp;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.util.Log;
/**
* @author tuomas
* This class provides basic helper functions and features for network communication.
*/
public class NetworkHelper
{
private Context mContext;
public NetworkHelper(Context mContext)
{
//get context
this.mContext = mContext;
}
/**
* Checks if the network connection is available.
*/
public boolean checkConnection()
{
//checks if the network connection exists and works as should be
ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected())
{
//network connection works
Log.v("log", "Network connection works");
return true;
}
else
{
//network connection won't work
Log.v("log", "Network connection won't work");
return false;
}
}
public void downloadUrl(String stringUrl)
{
new DownloadWebpageTask().execute(stringUrl);
}
//actual code to handle download
private class DownloadWebpageTask extends AsyncTask<String, Void, String>
{
@Override
protected String doInBackground(String... urls)
{
// params comes from the execute() call: params[0] is the url.
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return "Unable to retrieve web page. URL may be invalid.";
}
}
// Given a URL, establishes an HttpUrlConnection and retrieves
// the web page content as a InputStream, which it returns as
// a string.
private String downloadUrl(String myurl) throws IOException
{
InputStream is = null;
// Only display the first 500 characters of the retrieved
// web page content.
int len = 500;
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 );
conn.setConnectTimeout(15000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
int response = conn.getResponseCode();
Log.d("log", "The response is: " + response);
is = conn.getInputStream();
// Convert the InputStream into a string
String contentAsString = readIt(is, len);
return contentAsString;
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
}
// Reads an InputStream and converts it to a String.
public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException
{
Reader reader = null;
reader = new InputStreamReader(stream, "UTF-8");
char[] buffer = new char[len];
reader.read(buffer);
return new String(buffer);
}
// onPostExecute displays the results of the AsyncTask.
@Override
protected void onPostExecute(String result)
{
//textView.setText(result);
Log.v("log", result);
}
}
}
在我的活动类中,我使用这种方式:
connHelper = new NetworkHelper(this);
...
if (connHelper.checkConnection())
{
//connection ok, download the webpage from provided url
connHelper.downloadUrl(stringUrl);
}
我遇到的问题是我应该以某种方式回调活动,它应该可以在“downloadUrl()”函数中定义 . 例如,当下载完成时,将调用活动中的public void“handleWebpage(String data)”函数,并将加载的字符串作为其参数 .
我做了一些谷歌搜索,发现我应该以某种方式使用接口来实现这个功能 . 在审查了几个类似的stackoverflow问题/答案后,我没有确定我是否正确理解了接口:How do I pass method as a parameter in Java?老实说,使用匿名类对我来说是新的,我不确定我应该在哪里或如何应用示例代码片段提到的线程 .
所以我的问题是如何将回调函数传递给我的网络类并在下载完成后调用它?接口声明的位置,实现关键字等等?请注意我是Java的初学者(虽然有其他编程背景)所以我很感激整个解释:)谢谢!
6 回答
使用带有抽象回调方法的回调接口或抽象类 .
回调接口示例:
第二种选择更简洁 . 你甚至不需要为"onDownloaded event"定义一个抽象方法,因为
onPostExecute
确实需要它 . 只需在downloadUrl
方法中使用匿名内联类扩展DownloadWebpageTask
.是的,界面是恕我直言的最佳方式 . 例如,GWT使用带有如下界面的命令模式:
通过这种方式,您可以将函数从方法传递到另一个方法
NO interface, NO lib, NO Java 8 needed!
刚刚从
java.util.concurrent
使用Callable<V>
How to use it:
myParamMethod()
是我们传递的方法作为参数(在本例中为methodParam
) .开箱即用的解决方案是Java中不可能实现这一点 . Java不接受Higher-order functions . 它可以通过一些"tricks"来实现 . 通常,界面是您看到的那个 . 请查看here了解更多信息 . 您也可以使用反射来实现它,但这很容易出错 .
使用接口可能是Java编码体系结构中的最佳方式 .
但是,传递一个Runnable对象也可以正常工作,我认为它会更加实用和灵活 .
反射从来都不是一个好主意,因为它更难以阅读和调试,但如果你100%确定你正在做什么,你可以简单地调用类似set_method(R.id.button_profile_edit,“toggle_edit”)的方法来附加一个方法一个看法 . 这在片段中很有用,但有些人会认为它是反模式所以要警告 .