2013-07-04 3 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); 

Что я делаю неправильно? Он сообщает мне, что контекст не может быть разрешен для типа, хотя я импортировал android.content.Context. Я попытался создать экземпляр контекста, но я тоже не могу этого сделать.

+0

Кажется, вам не нужен «mainContext.this» Вы пробовали просто (активность) mainContext? Собственно, сам контекст не имеет метода findViewById(). – sandrstar

+0

Whelp, похоже, что я неправильно прочитал и включил контекст вместо Activity. Но разве это не заставило бы мою деятельность просачиваться в другой класс? – 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); 
    } 
} 

Edit:

В качестве альтернативы.

Вы можете определить интерфейс в asycntask и присвоить свой класс активности интерфейсу.

+0

Я не очень хорошо знаком с интерфейсами или как это вообще работает, есть ли где-нибудь, что я могу прочитать на нем? – Sefam

+0

@Sefam читать java docs на интерфейсе моего оракула. 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 - попробуйте сделать вместо этого mainContext типа Activity.

+0

Я понимаю, что я испортил. Причина, по которой я попытался использовать Context, заключается в том, что последний ответ на этот вопрос здесь: http://stackoverflow.com/questions/4979454/the-method-findviewbyidint-is-undefined четко говорит, что, если я не знаю, m, моя активность может протекать в других классах. Должен ли я так делать? – Sefam

+1

@Sefam - есть много способов сделать это, но важная часть заключается в том, что вы не держите длинную ссылку на ** любой ** 'Context'. В вашем случае «AsyncTask» (и его ссылка на вашу «активность») будет работать только до тех пор, пока запущена ваша «AsyncTask». После завершения и завершения 'onPostExecute', тогда' AsyncTask' уничтожается, а также ссылается на вашу «активность». – ianhanniballake

1

Заменить

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

с

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

и ошибка должна уйти.

+0

Как сказал нижеприведенный парень, в классе Context есть метод findViewById, и я должен заменить его на 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

Смежные вопросы