简体   繁体   中英

Why I can't set adapter in AsyncTask for ListView from another class?

I have MainActivity class and AsyncTask class. I had working version of code, but later I decided to separate AsyncTask class in another package. After this I get some problems and I am trying to solve them. This is last working version of my code.

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

I have trouble with adapter from MainActivity class. This is code for new AsyncTask class in another package. I have NullPointerException in line mainActivity.listView.setAdapter(mainActivity.adapter); Can you tell me why?

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

Because you are making direct reference of MainActivity's member fields from AsyncTask with creating MainActivity constructor which is wrong.

Just pass what ever member fields you want in AsyncTask's constructor and use that one,

Like,

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

And remove, MainActivity mainActivity = new MainActivity();

Now call AsyncTask from Activity like,

newPostsAsyncTask = new NewPostsAsyncTask(MainActivity.this, listView);
newPostsAsyncTask.execute();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM