Java에서 매개 변수로 함수 전달
저는 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)"함수가로드 된 문자열을 매개 변수로 사용하여 호출됩니다.
인터넷 검색을 수행 한 결과이 기능을 사용하려면 인터페이스를 사용해야한다는 것을 알았습니다. 몇 가지 유사한 스택 오버플로 질문 / 답변을 검토 한 후에도 작동하지 않았고 인터페이스를 제대로 이해했는지 확실하지 않습니다. Java에서 메서드를 매개 변수로 전달하는 방법은 무엇입니까? 솔직히 말해서 익명 클래스를 사용하는 것은 저에게 새로운 것이며 언급 된 스레드에서 예제 코드 스 니펫을 어디에 어떻게 적용해야하는지 잘 모르겠습니다.
그래서 내 질문은 콜백 함수를 네트워크 클래스에 전달하고 다운로드가 완료된 후 호출하는 방법입니다. 인터페이스 선언은 어디로 가고 키워드를 구현합니까? 저는 Java 초보자이므로 (다른 프로그래밍 배경이 있음) 전체 설명에 감사드립니다 :) 감사합니다!
콜백 인터페이스 또는 추상 콜백 메서드가있는 추상 클래스를 사용합니다.
콜백 인터페이스 예 :
public class SampleActivity extends Activity {
//define callback interface
interface MyCallbackInterface {
void onDownloadFinished(String result);
}
//your method slightly modified to take callback into account
public void downloadUrl(String stringUrl, MyCallbackInterface callback) {
new DownloadWebpageTask(callback).execute(stringUrl);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//example to modified downloadUrl method
downloadUrl("http://google.com", new MyCallbackInterface() {
@Override
public void onDownloadFinished(String result) {
// Do something when download finished
}
});
}
//your async task class
private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
final MyCallbackInterface callback;
DownloadWebpageTask(MyCallbackInterface callback) {
this.callback = callback;
}
@Override
protected void onPostExecute(String result) {
callback.onDownloadFinished(result);
}
//except for this leave your code for this class untouched...
}
}
두 번째 옵션은 훨씬 더 간결합니다. onPostExecute
정확히 필요한 것처럼 "onDownloaded 이벤트"에 대한 추상 메서드를 정의 할 필요조차 없습니다 . 메서드 DownloadWebpageTask
내에서 익명의 인라인 클래스로 확장하십시오 downloadUrl
.
//your method slightly modified to take callback into account
public void downloadUrl(String stringUrl, final MyCallbackInterface callback) {
new DownloadWebpageTask() {
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
callback.onDownloadFinished(result);
}
}.execute(stringUrl);
}
//...
인터페이스, lib, Java 8이 필요하지 않습니다!
그냥 사용 Callable<V>
에서java.util.concurrent
public static void superMethod(String simpleParam, Callable<Void> methodParam) {
//your logic code [...]
//call methodParam
try {
methodParam.call();
} catch (Exception e) {
e.printStackTrace();
}
}
이것을 어떻게 사용 하는가:
superMethod("Hello world", new Callable<Void>() {
public Void call() {
myParamMethod();
return null;
}
}
);
myParamMethod()
매개 변수로 전달 된 메소드는 어디에 있습니까 (이 경우 methodParam
).
예, 인터페이스는 IMHO의 가장 좋은 방법입니다. 예를 들어 GWT는 다음과 같은 인터페이스와 함께 명령 패턴을 사용합니다.
public interface Command{
void execute();
}
이런 식으로 메서드에서 다른 메서드로 함수를 전달할 수 있습니다.
public void foo(Command cmd){
...
cmd.execute();
}
public void bar(){
foo(new Command(){
void execute(){
//do something
}
});
}
The out of the box solution is that this is not possible in Java. Java does not accept Higher-order functions. It can be achieved though by some "tricks". Normally the interface is the one used as you saw. Please take a look here for further information. You can also use reflection to achieve it, but this is error prone.
Using Interfaces may be the best way in Java Coding Architecture.
But, passing a Runnable object could work as well, and it would be much more practical and flexible, I think.
SomeProcess sp;
public void initSomeProcess(Runnable callbackProcessOnFailed) {
final Runnable runOnFailed = callbackProcessOnFailed;
sp = new SomeProcess();
sp.settingSomeVars = someVars;
sp.setProcessListener = new SomeProcessListener() {
public void OnDone() {
Log.d(TAG,"done");
}
public void OnFailed(){
Log.d(TAG,"failed");
//call callback if it is set
if (runOnFailed!=null) {
Handler h = new Handler();
h.post(runOnFailed);
}
}
};
}
/****/
initSomeProcess(new Runnable() {
@Override
public void run() {
/* callback routines here */
}
});
Reflection is never a good idea since it's harder to read and debug, but if you are 100% sure what you're doing, you can simply call something like set_method(R.id.button_profile_edit, "toggle_edit") to attach a method to a view. This is useful in fragment, but again, some people would consider it as anti-pattern so be warned.
public void set_method(int id, final String a_method)
{
set_listener(id, new View.OnClickListener() {
public void onClick(View v) {
try {
Method method = fragment.getClass().getMethod(a_method, null);
method.invoke(fragment, null);
} catch (Exception e) {
Debug.log_exception(e, "METHOD");
}
}
});
}
public void set_listener(int id, View.OnClickListener listener)
{
if (root == null) {
Debug.log("WARNING fragment", "root is null - listener not set");
return;
}
View view = root.findViewById(id);
view.setOnClickListener(listener);
}
참고URL : https://stackoverflow.com/questions/16800711/passing-function-as-a-parameter-in-java
'Program Tip' 카테고리의 다른 글
CSV 파일에 대해 쉼표와 큰 따옴표를 동시에 이스케이프하는 방법은 무엇입니까? (0) | 2020.11.26 |
---|---|
SharedPreferences를 사용하여 문자열 세트를 저장하려고 할 때의 오작동 (0) | 2020.11.26 |
C ++의 함수 이름 : 대문자 사용 여부? (0) | 2020.11.26 |
C # 일반 사전에서 값 필터링 (0) | 2020.11.26 |
emacs에게 C ++ 모드에서 .h 파일을 열도록 지시하는 방법은 무엇입니까? (0) | 2020.11.26 |