0

我有MainActivity类和AsyncTask类。我有工作版本的代码,但后来我决定在另一个包中分离AsyncTask类。在此之后,我遇到了一些问题,我正试图解决它们。这是我的代码的最后一个工作版本。为什么我无法在AsyncTask中为另一个类的ListView设置适配器?

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, SwipeRefreshLayout.OnRefreshListener { 

    private static final String TAG = "MainActivity"; 
    private static final int LAYOUT = R.layout.activity_main; 
    private static final String URL = "http://killpls.me"; 

    private Toolbar toolbar; 
    private DrawerLayout drawerLayout; 
    private NavigationView navigationView; 
    private ActionBarDrawerToggle toggle; 
    private FloatingActionButton fab; 
    private ProgressDialog progressDialog; 
    private SwipeRefreshLayout mSwipeRefreshLayout; 

    private NewPostsAsyncTask newPostsAsyncTask; 

    public Elements content; 
    public ArrayList<String> titleList = new ArrayList<String>(); 
    public ArrayAdapter<String> adapter; 
    public ListView listView; 

    private int navigationDrawerItemId; 
    private boolean isNavigationDrawerItemEnabled = false; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(LAYOUT); 

     initToolbar(); 
     initNavigationView(); 
     initActionBarDrawerToggle(); // Добавляет возможность открыть NavigationDrawer через значок 
     initFloatingActionButton(); 
     initSwipeRefreshLayout(); 

     listView = (ListView) findViewById(R.id.listView); 
    } 

    private void initToolbar() { 
     toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 
     toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { 
      @Override 
      public boolean onMenuItemClick(MenuItem item) { 
       return false; 
      } 
     }); 
    } 

    private void initNavigationView() { 
     drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 
     navigationView = (NavigationView) findViewById(R.id.nav_view); 
     navigationView.setNavigationItemSelectedListener(this); 
    } 

    private void initActionBarDrawerToggle() { 
     toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 
     drawerLayout.setDrawerListener(toggle); 
     toggle.syncState(); 
    } 

    private void initFloatingActionButton() { 
     fab = (FloatingActionButton) findViewById(R.id.fab); 
     fab.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 
         .setAction("Action", null).show(); 
      } 
     }); 
    } 

    private void initSwipeRefreshLayout() { 
     mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container); 
     mSwipeRefreshLayout.setOnRefreshListener(this); 
     mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright, 
       android.R.color.holo_green_light, 
       android.R.color.holo_orange_light, 
       android.R.color.holo_red_light); 
    } 

    @Override 
    public void onBackPressed() { 
     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
     if (drawer.isDrawerOpen(GravityCompat.START)) { 
      drawer.closeDrawer(GravityCompat.START); 
     } else { 
      super.onBackPressed(); 
     } 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 

    @SuppressWarnings("StatementWithEmptyBody") 
    @Override 
    public boolean onNavigationItemSelected(MenuItem item) { 
     // Handle navigation view item clicks here. 
     navigationDrawerItemId = item.getItemId(); 

     if (navigationDrawerItemId == R.id.new_posts) { 
      Log.i(TAG, "Выбрано раздел \"Новые\" в Navigation Drawer"); 
      adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.item, titleList); 
      newPostsAsyncTask = new NewPostsAsyncTask(); 
      newPostsAsyncTask.execute(); 
      if (!adapter.isEmpty()) adapter.clear(); 
      isNavigationDrawerItemEnabled = true; 
     } else if (navigationDrawerItemId == R.id.moderation) { 
      Log.i(TAG, "Выбрано раздел \"Модерация\" в Navigation Drawer"); 
      adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.item, titleList); 
      if (!adapter.isEmpty()) adapter.clear(); 
      isNavigationDrawerItemEnabled = true; 
     } else if (navigationDrawerItemId == R.id.tell_story) { 
      Log.i(TAG, "Выбрано раздел \"Рассказать историю\" в Navigation Drawer"); 
      adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.item, titleList); 
      if (!adapter.isEmpty()) adapter.clear(); 
      isNavigationDrawerItemEnabled = true; 
     } else if (navigationDrawerItemId == R.id.most_terrible_stories) { 
      Log.i(TAG, "Выбрано раздел \"Самые страшные\" в Navigation Drawer"); 
      adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.item, titleList); 
      if (!adapter.isEmpty()) adapter.clear(); 
      isNavigationDrawerItemEnabled = true; 
     } else if (navigationDrawerItemId == R.id.random_story) { 
      Log.i(TAG, "Выбрано раздел \"Случайная\" в Navigation Drawer"); 
      adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.item, titleList); 
      if (!adapter.isEmpty()) adapter.clear(); 
      isNavigationDrawerItemEnabled = true; 
     } else if (navigationDrawerItemId == R.id.happy_end) { 
      Log.i(TAG, "Выбрано раздел \"Happy end\" в Navigation Drawer"); 
      adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.item, titleList); 
      if (!adapter.isEmpty()) adapter.clear(); 
      isNavigationDrawerItemEnabled = true; 
     } else if (navigationDrawerItemId == R.id.about_project) { 
      Log.i(TAG, "Выбрано раздел \"О проекте\" в Navigation Drawer"); 
      adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.item, titleList); 
      if (!adapter.isEmpty()) adapter.clear(); 
      isNavigationDrawerItemEnabled = true; 
     } else if (navigationDrawerItemId == R.id.help_all) { 
      Log.i(TAG, "Выбрано раздел \"Хочу помочь всем\" в Navigation Drawer"); 
      adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.item, titleList); 
      if (!adapter.isEmpty()) adapter.clear(); 
      isNavigationDrawerItemEnabled = true; 
     } 

     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
     drawer.closeDrawer(GravityCompat.START); 
     return true; 
    } 

    @Override 
    public void onRefresh() { 
     new Handler().postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       if (navigationDrawerItemId == R.id.new_posts) { 
        Log.i(TAG, "Обновленно раздел \"Новые\" в Navigation Drawer"); 
        newPostsAsyncTask = new NewPostsAsyncTask(); 
        newPostsAsyncTask.execute(); 
       } else if (navigationDrawerItemId == R.id.moderation) { 
        Log.i(TAG, "Обновленно раздел \"Модерация\" в Navigation Drawer"); 
       } else if (navigationDrawerItemId == R.id.tell_story) { 
        Log.i(TAG, "Обновленно раздел \"Рассказать историю\" в Navigation Drawer"); 
       } else if (navigationDrawerItemId == R.id.most_terrible_stories) { 
        Log.i(TAG, "Обновленно раздел \"Самые страшные\" в Navigation Drawer"); 
       } else if (navigationDrawerItemId == R.id.random_story) { 
        Log.i(TAG, "Обновленно раздел \"Случайная\" в Navigation Drawer"); 
       } else if (navigationDrawerItemId == R.id.happy_end) { 
        Log.i(TAG, "Обновленно раздел \"Happy end\" в Navigation Drawer"); 
       } else if (navigationDrawerItemId == R.id.about_project) { 
        Log.i(TAG, "Обновленно раздел \"О проекте\" в Navigation Drawer"); 
       } else if (navigationDrawerItemId == R.id.help_all) { 
        Log.i(TAG, "Обновленно раздел \"Хочу помочь всем\" в Navigation Drawer"); 
       } else { 
        Log.i(TAG, "Попытка обновить главную страницу"); 
       } 

       // Когда обновление закончено, вызываем метод setRefreshing(boolean) и передаем ему false. 
       mSwipeRefreshLayout.setRefreshing(false); 
      } 
     }, 2000); 

     if (!adapter.isEmpty()) adapter.clear(); 
    } 

    class NewPostsAsyncTask extends AsyncTask<String, Void, String> { 

     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 

      if (!isNavigationDrawerItemEnabled) { 
       progressDialog = new ProgressDialog(MainActivity.this); 
       progressDialog.setTitle("Новые"); 
       progressDialog.setMessage("Загрузка..."); 
       progressDialog.setIndeterminate(false); 
       progressDialog.show(); 
      } 
     } 

     @Override 
     protected String doInBackground(String... params) { 
      Document doc; 
      try { 
       doc = Jsoup.connect(URL).get(); // Считываем заголовок страницы 

       // Получение номера страницы селектором и преобразование его в число 
       Elements pageSpan = doc.select("div.paginator > span:first-child"); 
       int pageCount = Integer.parseInt(pageSpan.first().text()); 
       // Стоит еще проверить, что элементы нашлись, вызовом !pageSpan.isEmpty(), 
       // first() для пустого списка возвращает null. 

       for (int i = pageCount; i > 0; i--) { 
        String pageCountString = Integer.toString(i); 
        doc = Jsoup.connect("http://killpls.me/page/" + pageCountString).get(); 
        parseDocument(doc); 
        if (i == 1697) { 
         break; // Ограничение до 1697 страницы, чтобы не лагало. Надо исправить. 
        } 
       } 

      } catch (IOException e) { 
       e.printStackTrace(); // Если не получилось считать 
      } 
      return null; 
     } 

     @Override 
     protected void onPostExecute(String s) { 
      super.onPostExecute(s); 
      listView.setAdapter(adapter); 
      progressDialog.dismiss(); 
     } 
    } 

    public void parseDocument(Document doc) { 

     // Парсит посты на странице 
     content = doc.select("[style=margin:0.5em 0;line-height:1.785em]"); 

     for (Element contents : content) { 
      if (!contents.text().contains("18+")) { 
       // Выводит только посты без ссылки на 18+ 
       titleList.add(contents.text()); 
      } 
     } 
    } 
} 

我无法从MainActivity类的适配器。这是另一个包中的新AsyncTask类的代码。我在第mainActivity.listView.setAdapter(mainActivity.adapter);行中有NullPointerException你能告诉我为什么吗?

public class NewPostsAsyncTask extends AsyncTask<String, Void, String> { 

    private static final String URL = "http://killpls.me"; 
    private ProgressDialog progressDialog; 
    private Elements content; 

    private Context context; 

    public NewPostsAsyncTask(Context context) { 
     this.context = context; 
    } 

    MainActivity mainActivity = new MainActivity(); 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 

     if (!MainActivity.isNavigationDrawerItemEnabled) { 
      progressDialog = new ProgressDialog(context); //MainActivity.this 
      progressDialog.setTitle("Новые"); 
      progressDialog.setMessage("Загрузка..."); 
      progressDialog.setIndeterminate(false); 
      progressDialog.show(); 
     } 
    } 

    @Override 
    protected String doInBackground(String... params) { 
     Document doc; 
     try { 
      doc = Jsoup.connect(URL).get(); // Считываем заголовок страницы 

      // Получение номера страницы селектором и преобразование его в число 
      Elements pageSpan = doc.select("div.paginator > span:first-child"); 
      int pageCount = Integer.parseInt(pageSpan.first().text()); 
      // Стоит еще проверить, что элементы нашлись, вызовом !pageSpan.isEmpty(), 
      // first() для пустого списка возвращает null. 

      for (int i = pageCount; i > 0; i--) { 
       String pageCountString = Integer.toString(i); 
       doc = Jsoup.connect("http://killpls.me/page/" + pageCountString).get(); 
       parseDocument(doc); 
       if (i == 1697) { 
        break; // Ограничение до 1697 страницы, чтобы не лагало. Надо исправить. 
       } 
      } 

     } catch (IOException e) { 
      e.printStackTrace(); // Если не получилось считать 
     } 
     return null; 
    } 

    private void parseDocument(Document doc) { 
     // Парсит посты на странице 
     content = doc.select("[style=margin:0.5em 0;line-height:1.785em]"); 

     for (Element contents : content) { 
      if (!contents.text().contains("18+")) { 
       // Выводит только посты без ссылки на 18+ 

       mainActivity.titleList.add(contents.text()); 
       //titleList.add(contents.text()); 
      } 
     } 
    } 

    @Override 
    protected void onPostExecute(String s) { 
     super.onPostExecute(s); 

     mainActivity.listView.setAdapter(mainActivity.adapter); 
     //listView.setAdapter(adapter); 
     progressDialog.dismiss(); 
    } 
} 
+1

首先,你不能通过调用来实例化MainActivity新的MainActivity()'。 Android不能这样工作。其次,无论如何,'listView'是私人的,这意味着你不能在MainActivity类之外访问它。你需要做的是编写一个回调函数,将你的'AsyncTask'的结果返回给你的MainActivity。这是完成你正在尝试做的事情的正确方法。 – NoChinDeluxe

+0

@NoChinDeluxe哦,对不起。我从我的github复制了这段代码。现在在我的项目中我有公共字段: public ArrayList titleList = new ArrayList (); public ArrayAdapter adapter; public ListView listView; 但它不起作用。 如何正确地将此回调与结果写入MainActivity? – Kostya

回答

1

因为你正在从的AsyncTask MainActivity的成员字段的直接引用与创建MainActivity构造这是不对的。

只是通过你想要什么都成员字段中的AsyncTask的构造和使用一个,

一样,

private Context context; 
private ListView mListView; 
private ArrayAdapter<String> adapter; 
private List<String> titleList = new ArrayList<String>(); 

public NewPostsAsyncTask(Context context, ListView listview) { 
     this.context = context; 
     this.mListView = listview; 
    } 

private void parseDocument(Document doc) { 
     // Парсит посты на странице 
     content = doc.select("[style=margin:0.5em 0;line-height:1.785em]"); 

     for (Element contents : content) { 
      if (!contents.text().contains("18+")) { 
       // Выводит только посты без ссылки на 18+ 
       titleList.add(contents.text()); 
      } 
     } 
    } 


    @Override 
    protected void onPostExecute(String s) { 
     super.onPostExecute(s); 
     adapter = new ArrayAdapter<String>(context, R.layout.list_item, R.id.item, titleList); 
     mListView.setAdapter(adapter); 
     progressDialog.dismiss(); 
    } 
} 

和删除,MainActivity mainActivity = new MainActivity();

现在从活动调用的AsyncTask一样,

newPostsAsyncTask = new NewPostsAsyncTask(MainActivity.this, listView); 
newPostsAsyncTask.execute(); 
相关问题