newbieandroid
newbieandroid

Reputation: 161

Why is AsyncTask working on the main thread?

I'm trying to use AsyncTask to do a task in the background and then present it when it is done, but what happens is that nothing is displayed until it is done.

I also tried to use execute and doInBackground to call it, but both cause the same issue and I have to wait for the activity to start with everything ready rather than show a page with the loading progress bar and then add the list later.

Code:

private class listTask extends AsyncTask<Void,Void,Void> {
    @Override
    protected Void doInBackground(Void... voids) {
        recyclerview.setAdapter(new ItemAdapter(getInternalFileList()));
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        progressbar.setVisibility(View.GONE);
    }

    List<GalleryItem> getInternalFileList(){
        String path = getActivity().getFilesDir().toString();
        File directory = new File(path);
        File[] files = directory.listFiles();
        List<GalleryItem> galleryItems = new ArrayList<>();

        MainDBRepository repo = new MainDBRepository(getActivity());
        HashMap<String,GalleryItem> itemsMap = repo.getItemsMap();

        for(File file : files) {
            if(itemsMap.containsKey(file.getName()))
                galleryItems.add(itemsMap.get(file.getName()));
        }

        Collections.reverse(galleryItems);

        return galleryItems;
    }

    private class ItemHolder extends RecyclerView.ViewHolder {
        ImageView mItemImageView;

        ItemHolder(View itemView) {
            super(itemView);
            mItemImageView = (ImageView) itemView.findViewById(R.id.image_view);
        }

        public void bindBackgroundImage(Bitmap backgroundImage){
            mItemImageView.setImageBitmap(backgroundImage);
        }

        public void bindImageViewer(final String path){
            mItemImageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = ImageViewerActivity.newIntent(getActivity(), path);
                    startActivity(intent);
                }
            });
        }
    }

    private class ItemAdapter extends RecyclerView.Adapter<ItemHolder> {
        private List<GalleryItem> galleryItems;

        ItemAdapter(List<GalleryItem> galleryItems) {
            galleryItems = galleryItems;
        }

        @NonNull
        @Override
        public ItemHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
            LayoutInflater inflater = LayoutInflater.from(getActivity());
            View v = inflater.inflate(R.layout.gallery_item, viewGroup, false);
            return new ItemHolder(v);
        }

        @Override
        public void onBindViewHolder(@NonNull ItemHolder itemHolder, int position) {
            GalleryItem galleryItem = galleryitems.get(position);
            String path = getActivity().getFilesDir() + "/" + galleryItem.getID();
            File file = new File(path);
            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
            itemHolder.bindBackgroundImage(bitmap);
            itemHolder.bindImageViewer(path);
        }

        @Override
        public int getItemCount() {
            return galleryitems.size();
        }
    }
}

Upvotes: 10

Views: 1893

Answers (2)

simo-r
simo-r

Reputation: 733

If you want to show something in the UI while the AsyncTask is computing the background task you should implement the onProgressUpdate(Progress... values) method which is called from publishProgress(Progress... values) and implements the logic under the background task progress. In your code you just show the final result in the onPostExecute(). Note that the AsyncTask run the doInBackground() method in a different thread than the UI thread and onProgressUpdate() and onPostExecute() on the UI thread because they should update UI. For more info refer to the Android Doc about AsyncTask.

Upvotes: 9

ligi
ligi

Reputation: 39529

On the background just means - not on the UI - thread. To get results before the job is finished you will need to feed results to the UI thread while doing the job on the background. To get results on the UI thread before you can use AsyncTask.onProgressUpdate(..) - or better use kotlin coroutines instead of asynctask.

Upvotes: 5

Related Questions