Как заставить методы пользовательского интерфейса ждать асинхронную задачу? - PullRequest
0 голосов
/ 07 мая 2019

У меня есть два массива (groupID, groupNames), которые мне нужно заполнить переменными, полученными из определенных URL-адресов, что делается внутри подкласса, расширяющего AsyncTask, так как в противном случае это приводит к ошибке NetworkOnMainThreadException. Проблема в том, что мне нужно убедиться, что эти два массива заполнены до вызова initRecyclerView(); в потоке пользовательского интерфейса.

Как я могу убедиться, что мой код ожидает завершения асинхронной передачи перед выполнением initRecyclerView();?

public class GroupPage extends AppCompatActivity {

    private static final String TAG = "RecycleViewAdapter";
    private ArrayList<Integer> groupIDs = new ArrayList<>();
    private ArrayList<String> groupNames = new ArrayList<>();

    private class groupPageConnect extends AsyncTask {
        @Override
        protected Object doInBackground(Object... arg0) {

            try{
                System.out.println("Testing 1 - Send Http GET request");
                getGroups();

            } catch (Exception e) {
                System.err.println("Oops!");
                e.printStackTrace();
            }
            return null;
        }
    }

    private void getGroups() throws Exception{
        String url = "http://obsco.me/obsco/api/v1.0/users/12345671";
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("GET");
        con.setRequestProperty("User-Agent", "Mozilla/5.0");

        int responseCode = con.getResponseCode();
        System.out.println("Response Code  for IDs: " + responseCode);

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        JSONObject reader = new JSONObject(response.toString());
        JSONArray allContainingArray = reader.getJSONArray("users");
        JSONObject userJSON  = (JSONObject) allContainingArray.get(0);
        JSONArray temp = userJSON.getJSONArray("groups");

        Log.d(TAG, "initializing");
        for (int x = 0; x < temp.length(); x++){
            //System.out.println(temp.getJSONObject(x).getInt("id"));
            groupIDs.add(temp.getJSONObject(x).getInt("id"));
            System.out.println(groupIDs.size() );
            System.out.println(groupIDs.get(x));
            //groupNames.add("Dummy");

            url = "http://obsco.me/obsco/api/v1.0/groupname/" + groupIDs.get(x);
            System.out.println("ar1");
            obj = new URL(url);
            System.out.println("ar2");
            con = (HttpURLConnection) obj.openConnection();
            con.setRequestMethod("GET");
            con.setRequestProperty("User-Agent", "Mozilla/5.0");

            responseCode = con.getResponseCode();
            System.out.println("Response Code  for IDs: " + responseCode);

            in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            response = new StringBuffer();
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            reader = new JSONObject(response.toString());
            System.out.println(reader.getString("name"));
            groupNames.add(reader.getString("name"));
        }

    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_group_page);
        Log.d(TAG, "started");
        try {
            groupPageInit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void groupPageInit() throws Exception{
        new groupPageConnect().execute();
        initRecyclerView();
    }

    private void initRecyclerView(){
        Log.d(TAG, "initializingRecyclerView");
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        RecyclerViewAdapter adapter = new RecyclerViewAdapter( this, groupIDs, groupNames);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager( new LinearLayoutManager( this));
    }
}

Ответы [ 4 ]

0 голосов
/ 09 мая 2019

После того, как AsyncTask завершит свою работу, он вызовет метод onPostExecute() для обновления пользовательского интерфейса (в вашем случае выполните код в методе initRecyclerView ()). Кроме того, вы должны использовать WeakReference , чтобы предотвратить утечку контекста активности GroupPage.

Вот мое решение:

public class GroupPage extends AppCompatActivity {

    private static final String TAG = "RecycleViewAdapter";

    private ArrayList<Integer> groupIDs = new ArrayList<>();
    private ArrayList<String> groupNames = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_group_page);
        Log.d(TAG, "started");
        new GroupPageConnect(this).execute();
    }

    private void initRecyclerView(List<Integer> groupIds, List<String> groupNames) {
        this.groupIDs.addAll(groupIds);
        this.groupNames.addAll(groupNames);

        Log.d(TAG, "initializingRecyclerView");
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, this.groupIDs, this.groupNames);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
    }

    private static class GroupPageConnect extends AsyncTask<Void, Void, Group> {

        private WeakReference<GroupPage> mGroupPage;

        GroupPageConnect(GroupPage groupPage) {
            mGroupPage = new WeakReference<>(groupPage);
        }

        @Override
        protected Group doInBackground(Void... arg0) {
            try {
                System.out.println("Testing 1 - Send Http GET request");
                return getGroups();
            } catch (Exception e) {
                System.err.println("Oops!");
                e.printStackTrace();
                return null;
            }
        }

        private Group getGroups() throws Exception {
            Group group = new Group();

            String url = "http://obsco.me/obsco/api/v1.0/users/12345671";
            URL obj = new URL(url);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();
            con.setRequestMethod("GET");
            con.setRequestProperty("User-Agent", "Mozilla/5.0");

            int responseCode = con.getResponseCode();
            System.out.println("Response Code  for IDs: " + responseCode);

            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            JSONObject reader = new JSONObject(response.toString());
            JSONArray allContainingArray = reader.getJSONArray("users");
            JSONObject userJSON = (JSONObject) allContainingArray.get(0);
            JSONArray temp = userJSON.getJSONArray("groups");

            Log.d(TAG, "initializing");
            for (int x = 0; x < temp.length(); x++) {
                //System.out.println(temp.getJSONObject(x).getInt("id"));
                group.groupIds.add(temp.getJSONObject(x).getInt("id"));
                System.out.println(group.groupIds.size());
                System.out.println(group.groupIds.get(x));
                //groupNames.add("Dummy");

                url = "http://obsco.me/obsco/api/v1.0/groupname/" + group.groupIds.get(x);
                System.out.println("ar1");
                obj = new URL(url);
                System.out.println("ar2");
                con = (HttpURLConnection) obj.openConnection();
                con.setRequestMethod("GET");
                con.setRequestProperty("User-Agent", "Mozilla/5.0");

                responseCode = con.getResponseCode();
                System.out.println("Response Code  for IDs: " + responseCode);

                in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                response = new StringBuffer();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();

                reader = new JSONObject(response.toString());
                System.out.println(reader.getString("name"));
                group.groupNames.add(reader.getString("name"));
            }

            return group;
        }

        @Override
        protected void onPostExecute(Group group) {
            super.onPostExecute(group);

            GroupPage groupPage = mGroupPage.get();
            if (group == null) {
                return;
            }

            groupPage.initRecyclerView(group.groupIds, group.groupNames);
        }
    }

    static class Group {
        List<Integer> groupIds;
        List<String> groupNames;

        Group() {
            groupIds = new ArrayList<>();
            groupNames = new ArrayList<>();
        }
    }
}
0 голосов
/ 07 мая 2019

Вызовите метод initRecyclerView () для метода onPostExecute (result).Асинхронная задача определяется вычислением, которое выполняется в фоновом потоке и результаты которого публикуются в потоке пользовательского интерфейса.Асинхронная задача определяется 4 шагами, которые называются onPreExecute, doInBackground, onProgressUpdate и onPostExecute.onPostExecute (Result), вызываемыми в потоке пользовательского интерфейса после завершения фонового вычисления.

private class groupPageConnect extends AsyncTask<Object,void,String> {

        @Override
        protected Object doInBackground(Object... arg0) {
           //put your code here
        }

        @Override
        protected void onPostExecute(String result) {
             //call what you want to update
                        initRecyclerView();

            // dismiss progress dialog here
            // into onPostExecute() but that is upto you
        }

        @Override
        protected void onPreExecute() {
        // start progress dialog here
        }

        @Override
        protected void onProgressUpdate(Void... values) {
         // progress update here}
         }
     }
0 голосов
/ 07 мая 2019

Вы можете переопределить onPostExecute.

onPostExecute (Result), вызывается в потоке пользовательского интерфейса после завершения фоновых вычислений.Результат фоновых вычислений передается на этот шаг в качестве параметра. задача проходит 4 шага

Обратите внимание, что загрузка данных из сети через AsyncTask может быть причинойутечки памяти.

0 голосов
/ 07 мая 2019

После getGroups() вы можете использовать runOnUiThread().

Пример:

getGroups();
runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // Logic that you want to execute on main thread
                        initRecyclerView();
                    }
                });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...