2013-07-04 102 views
0

前幾天我開始關注Android開發。我試圖從REST API中獲取數據,並且使用AsyncTask類來完成HTTP事務。問題是,我無法爲我的主要活動獲取上下文,以便查找我的ListView並將其內容分配給onPostExecute()。上下文無法解析爲類型

這裏是MainActivity.java:

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     new DownloadMediaList(this).execute(); 
    } 
} 

這裏是DownloadMediaList.java:

public class DownloadMediaList extends AsyncTask<Void, Void, ArrayList<Media>> { 

    ListView listView = null; 
    Context mainContext = null; 

    public DownloadMediaList(Context main){ 
     this.mainContext = main; 
    } 

    @Override 
    protected void onPreExecute(){ 
     listView = (ListView) mainContext.this.findViewById(R.id.media_list); 
    } 

    // Operations that we do on a different thread. 
    @Override 
    protected ArrayList<Media> doInBackground(Void... params){ 
     // Set an ArrayList to store the medias. 
     ArrayList<Media> mediaList = new ArrayList<Media>(); 

     // Call the REST API and get the request info and media list in a JSONObject. 
     RESTFunctions restRequest = new RESTFunctions(); 
     JSONObject jsonMedia = restRequest.getMediaList(); 

     // Try catch to catch JSON exceptions. 
     try { 
      // Store the media list into a JSONArray. 
      JSONArray mediaArray = jsonMedia.getJSONArray("media"); 

      // Create an instance of media to store every single media later. 
      Media media = new Media(); 

      // Loop through the JSONArray and add each media to the ArrayList. 
      for (int i=0; i<mediaArray.length();i++){ 
       media = new Media(); 
       JSONObject singleMedia = mediaArray.getJSONObject(i); 
       media.setTitle(singleMedia.getString("titre")); 
       media.setYear(singleMedia.getString("annee")); 
       media.setLength(singleMedia.getString("duree")); 
       mediaList.add(media); 
      } 
     } catch (JSONException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     // Return the ArrayList. 
     return mediaList; 
    } 

    // Operations we do on the User Interface. Synced with the User Interface. 
    @Override 
    protected void onPostExecute(ArrayList<Media> mediaList){ 
     // Set TextViews in ListViews here 
    } 
} 

這些類兩個單獨的文件。

此行特別是給我找麻煩:

listView = (ListView) mainContext.this.findViewById(R.id.media_list); 

我在做什麼錯?它告訴我Context無法解析爲一個類型,即使我已經導入了android.content.Context。我嘗試了實例化上下文,但我無法做到這一點。

+0

似乎你不需要'mainContext.this'你試過(活動)mainContext?實際上,上下文本身沒有findViewById()方法。 – sandrstar

+0

Whelp,看起來像我讀錯了,並放在上下文而不是活動。但是這不會導致我的活動滲透到另一個班級嗎? – Sefam

+0

我基於自己最後的答案在這裏:http://stackoverflow.com/questions/4979454/the-method-findviewbyidint-is-undefined。在這種情況下,我應該怎麼做? – Sefam

回答

1

在您的活動類

public interface TheInterface { 
public void theMethod(ArrayList<Media> result); 

} 
    } 

然後

DownloadMediaList task = new DownloadMediaList (MainAactivity.this,new TheInterface() { 
      @Override 
      public void theMethod(ArrayList<Media> result) { 
       // result available here do whatever with list media 
      } 
     }); 

然後在的AsyncTask

Context mainContext = null; 
TheInterface mlistener; 
public DownloadMediaList(Context main,TheInterface listener){ 
    this.mainContext = main; 
    mlistener = listener; 
} 

然後在onPostExecute

@Override 
protected void onPostExecute(ArrayList<Media> mediaList){ 
    if (mlistener != null) 
    { 
     mlistener.theMethod(mediaList); 
    } 
} 

編輯:

作爲替代。

您可以在asycntask中定義接口並讓您的活動類實現接口。

+0

我對接口還不是很熟悉,或者它的功能如何,有沒有我可以閱讀的地方? – Sefam

+0

@Sefam閱讀界面我的oracle上的java文檔。 http://docs.oracle.com/javase/tutorial/java/concepts/interface.html – Raghunandan

+0

@Sefam你可以查看這個http://developer.android.com/guide/components/fragments.html。在這裏他們使用接口將值從片段傳遞給父活動。 – Raghunandan

1

Context s沒有意見,也沒有findViewById方法 - 嘗試使mainContextActivity代替。

+0

我知道我搞砸了。我嘗試使用上下文的原因是因爲這個問題的最後一個答案在這裏:http://stackoverflow.com/questions/4979454/the-method-findviewbyidint-is-undefined清楚地說,如果我不知道我'在做,我的活動可能會泄漏到其他類。我應該這樣做嗎? – Sefam

+1

@Sefam - 有很多方法可以做到這一點,但重要的一點是你不會持久地引用** any **'Context'。在你的情況下,只要你的'AsyncTask'正在運行,'AsyncTask'(及其對'Activity'的引用)就會存活。一旦它完成並且你的'onPostExecute'完成,那麼'AsyncTask'就會被銷燬,其對'Activity'的引用也會被銷燬。 – ianhanniballake

1

更換

listView = (ListView) mainContext.this.findViewById(R.id.media_list); 

listView = (ListView) mainContext.findViewById(R.id.media_list); 

和錯誤應該消失。

+0

正如下面的人所說,在Context類中找到了ViewById方法,並且我應該用Activity替換它,但據推測,我可以根據最後一個答案將我的Activity泄漏到這個類中:http://stackoverflow.com/問題/ 4979454/the-method-findviewbyidint-is-undefined – Sefam

+1

@Sefam有一個替代方案,您可以使用界面將值傳遞迴您的活動,然後更新ui。 – Raghunandan

+0

這不會是不同步的,並導致沒有回調的問題? – Sefam

1

您可以將AsyncTask作爲內部類添加到您的活動中。

public class MainActivity extends Activity { 
    private Context context; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    context=this; 
    new DownloadMediaList(this).execute(); 
} 

private class DownloadMediaList extends AsyncTask<Void, Void, ArrayList<Media>> { 

ListView listView = null; 




@Override 
protected void onPreExecute(){ 
    listView = (ListView) context.findViewById(R.id.media_list); 
} 

// Operations that we do on a different thread. 
@Override 
protected ArrayList<Media> doInBackground(Void... params){ 
    // Set an ArrayList to store the medias. 
    ArrayList<Media> mediaList = new ArrayList<Media>(); 

    // Call the REST API and get the request info and media list in a JSONObject. 
    RESTFunctions restRequest = new RESTFunctions(); 
    JSONObject jsonMedia = restRequest.getMediaList(); 

    // Try catch to catch JSON exceptions. 
    try { 
     // Store the media list into a JSONArray. 
     JSONArray mediaArray = jsonMedia.getJSONArray("media"); 

     // Create an instance of media to store every single media later. 
     Media media = new Media(); 

     // Loop through the JSONArray and add each media to the ArrayList. 
     for (int i=0; i<mediaArray.length();i++){ 
      media = new Media(); 
      JSONObject singleMedia = mediaArray.getJSONObject(i); 
      media.setTitle(singleMedia.getString("titre")); 
      media.setYear(singleMedia.getString("annee")); 
      media.setLength(singleMedia.getString("duree")); 
      mediaList.add(media); 
     } 
    } catch (JSONException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    // Return the ArrayList. 
    return mediaList; 
} 

// Operations we do on the User Interface. Synced with the User Interface. 
@Override 
protected void onPostExecute(ArrayList<Media> mediaList){ 
    // Set TextViews in ListViews here 
} 
    }} 
+0

這是強制性的嗎?我喜歡把我的東西分開。 – Sefam

+0

這不是強制性的。但是如果AsyncTask沒有被使用,你可以在同一個類中使用它。 –

+0

我可能會在以後的其他地方使用它。我有什麼選擇? – Sefam