java

2013-05-28 19 views
46

bir parametre olarak işlevini geçirerek Android framework ve Java ile aşina alıyorum ve sadece web sayfalarını aramak için izin veren ağ kodunun çoğunu işleyecek genel bir "NetworkHelper" sınıfı oluşturmak istedim. http://developer.android.com/training/basics/network-ops/connecting.htmljava

Kodu: Etkinliğimi sınıfta

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); 

    } 

} 

}

kullandığım bu şekilde sınıfını

benim ağ sınıfı oluşturmak için developer.android.com bu makaleyi takip :

connHelper = new NetworkHelper(this); 

...

if (connHelper.checkConnection()) 
    { 
     //connection ok, download the webpage from provided url 
     connHelper.downloadUrl(stringUrl); 
    } 

Sorun şu ki, bir şekilde geri arama yapmam gerekiyor ve "downloadUrl()" işlevinde tanımlanmalıdır. Örneğin, indirme bittiğinde, public void "handleWebpage (String data)" aktivitesindeki işlev, parametresi olarak yüklü dizeyle çağrılır.

Bazı çalışmalar yaptım ve bu işlevselliği sağlamak için bir şekilde arayüzler kullanmam gerektiğini öğrendim. Birkaç benzer stackoverflow soruları/cevaplarını gözden geçirdikten sonra çalışmayı başaramadım ve arayüzleri düzgün bir şekilde anladığımdan emin değilim: How do I pass method as a parameter in Java? Anonim sınıfları kullanarak dürüst olmak benim için yeni ve nerede ve nasıl emin değilim belirtilen koddaki örnek kod parçacıklarını uygulamalıdır.

Benim sorum, geri arama işlevini ağ sınıfımma nasıl iletebileceğimi ve indirme bittikten sonra nasıl arayabileceğimi anlatıyor? Arabirim bildirimi nereye gider, anahtar kelime vb. Uygular? Lütfen Java ile yeni başlayan biri olduğumu unutmayın (diğer programlama arka planınız olsa da), bu yüzden bir açıklama için minnettarım :) Teşekkürler!

cevap

75

Geri arama arabirimi veya soyut geri çağrı yöntemleri ile soyut bir sınıf kullanın.

Geri arama arayüzü örneğin:

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... 
    } 
} 

İkinci seçenek daha kısa olan. onPostExecute'un tam olarak ihtiyaç duyduğu gibi "onDownloaded event" için soyut bir yöntem tanımlamanız bile gerekmez. downloadUrl yönteminizin içinde DownloadWebpageTask adınızı bir anonim satır içi sınıfıyla genişletmeniz yeterlidir.

//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); 
    } 

    //... 
+1

sayesinde bu sorunu çözmek için bana yardımcı oldu ve ben şimdi arayüzleri genel java programlama önemli bir rol oynamaktadır nasıl İlginç – Tumetsu

+1

görmek :) arayüzleri temellerini anlamak düşünüyorum. –

+3

Bu, java 8 ... –

20

Evet, bir arabirim, IMHO'nun en iyi yoludur. Örneğin, GWT böyle bir arayüz ile komut deseni kullanır:

public interface Command{ 
    void execute(); 
} 

Bu şekilde, kutu çözüm başka

public void foo(Command cmd){ 
    ... 
    cmd.execute(); 
} 

public void bar(){ 
    foo(new Command(){ 
    void execute(){ 
     //do something 
    } 
    }); 
} 
+6

'dan önce böyledir GWT nedir ve herhangi bir parametreyi nasıl geçireceksiniz? – Buksy

+0

@Buksy, neye bakıyorsunuz? public interface Komut { void execute (Nesne ... nesnesi); Eğer bunu tüm bir yorum olarak daha uygun olur içine bakmak ne önermek beri, D –

9

dışarı için bir yöntem ile ilgili fonksiyon geçebilir bu olmasıdır Java'da mümkün değildir. Java, Higher-order functions kabul etmez. Bazı "hileler" tarafından olsa da elde edilebilir. Normalde, arabirim gördüğünüz gibi kullanılır. Daha fazla bilgi için lütfen here'a bakın. Bunu elde etmek için yansımayı da kullanabilirsiniz, ancak bu hataya eğilimlidir.

+1

Bu bir cevap olarak gerçekten layık değildir: } sınırsız nesneleri geçirin. –

+8

50'den az temsilcisi olduğu için yorum yapamaz, sadece cevap verebilir. Bunu her zaman sevmedim. –

+1

Java'ya geçiş yapan deneyimli programcılar için çok yararlı bir kavramsal cevap. Teşekkürler, @olorin! – Fattie

4

kullanma Arayüzler Java Kodlama Architecture en iyi yol olabilir.

Ama bir Runnable nesneyi geçirmeden yanı işe yarayabilir ve çok daha pratik ve esnek olacaktır diye düşünüyorum. okunması ve hata ayıklama zordur çünkü

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 */ 
    } 
}); 
+1

Çok temiz ve düzenli bir uygulama. – SolidSnake

0

Yansıma iyi bir fikir asla, ama ne yaptığını% 100 eminseniz, sadece, "toggle_edit set_method gibi bir şey (R.id.button_profile_edit çağırabilir ") bir görünüme bir yöntem eklemek için. Bu, parçalarda yararlıdır, ama yine de, bazı insanlar bunu anti-desen olarak düşünürler, bu yüzden uyarılmalıdır.

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); 
} 
0

YOK arayüzü, YOK lib, YOK Java 8 gerekli!

Sadece Nasıl kullanılır 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(); 
    } 
} 

den Callable<V> kullanılarak:

superMethod("Hello world", new Callable<Void>() { 
       public Void call() { 
        myParamMethod(); 
        return null; 
       } 
      } 
    ); 

Nerede myParamMethod() (bu durumda methodParam olarak) parametre olarak bizim geçirilen yöntemdir.