0

I am developing news app user can download video and image.

So I developed navigation drawer with different fragment with material design. But I am facing some problem in it when I click gallery (where I show the downloaded video and images) it stuck for some time and then open fragment. it happened only in specific fragment but not all.

see Video here.

Here is my code:

MainActivity.java

public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {

    private static String TAG = MainActivity.class.getSimpleName();

    private Toolbar mToolbar;
    private FragmentDrawer drawerFragment;
    TextView mTitle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mToolbar = (Toolbar) findViewById(R.id.toolbar);

        setSupportActionBar(mToolbar);
        if (getSupportActionBar() != null)
        {
            getSupportActionBar().setDisplayShowHomeEnabled(true);
        }
        mTitle = (TextView) mToolbar.findViewById(R.id.tv_toolbar_title);

        drawerFragment = (FragmentDrawer)
                getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
        drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
        drawerFragment.setDrawerListener(this);

        // display the first navigation drawer view on app launch
        displayView(0);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.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;
        }


      /*  if (id == R.id.action_search) {
            Toast.makeText(getApplicationContext(), "Search action is selected!", Toast.LENGTH_SHORT).show();
            return true;
        }*/

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onDrawerItemSelected(View view, int position) {



        displayView(position);
    }

    private void displayView(int position) {
        Fragment fragment = null;
        String title = getString(R.string.app_name);
        switch (position) {
            case 0:
                fragment = new HomeFragment();
                title = getString(R.string.title_home);
                mTitle.setText(title);
                break;
            case 1:
                fragment = new GalleryFragment();
                title = getString(R.string.title_gallery);
                mTitle.setText(title);
                break;
            case 2:
                fragment = new SettingFragment();
                title = getString(R.string.title_setting);
                mTitle.setText(title);
                break;
            case 3:
                fragment = new AboutusFragment();
                title = getString(R.string.title_aboutus);
                mTitle.setText(title);
                break;
            case 4:
                fragment = new ContactusFragment();
                title = getString(R.string.title_contactus);
                mTitle.setText(title);
                break;
            default:
                break;
        }

        if (fragment != null) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.container_body, fragment);
            fragmentTransaction.commit();

            // set the toolbar title
            if (getSupportActionBar() != null)
            getSupportActionBar().setTitle(title);
        }
    }
}

FragmentDrawer.java

public class FragmentDrawer extends Fragment {

    private static String TAG = FragmentDrawer.class.getSimpleName();

    private RecyclerView recyclerView;
    private ActionBarDrawerToggle mDrawerToggle;
    private static DrawerLayout mDrawerLayout;
    private NavigationDrawerAdapter adapter;
    private View containerView;
    private static String[] titles = null;
    private static int[] ic_nav_drw = {R.drawable.ic_setting, R.drawable.gallery, R.drawable.setting, R.drawable.aboutus, R.drawable.contactus};
    private FragmentDrawerListener drawerListener;
    ImageView profile;
    TextView tv_name;

    public FragmentDrawer() {

    }

    public void setDrawerListener(FragmentDrawerListener listener) {
        this.drawerListener = listener;
    }

    public static List<NavDrawerItem> getData() {
        List<NavDrawerItem> data = new ArrayList<>();

        // preparing navigation drawer items
        for (int i = 0; i < titles.length; i++) {
            NavDrawerItem navItem = new NavDrawerItem();
            navItem.setTitle(titles[i]);
            navItem.setIcon(ic_nav_drw[i]);
            data.add(navItem);
        }
        return data;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // drawer labels
        titles = getActivity().getResources().getStringArray(R.array.nav_drawer_labels);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflating view layout
        View layout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
        recyclerView = (RecyclerView) layout.findViewById(R.id.drawerList);

        tv_name = (TextView) layout.findViewById(R.id.tv_name);
        profile = (ImageView) layout.findViewById(R.id.profile);

        SharedPreferences settings = getActivity().getSharedPreferences("preference", 0);
        String name = settings.getString("name","");
        tv_name.setText(name);

        profile.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(), "You click profile", Toast.LENGTH_SHORT).show();
            }
        });

        adapter = new NavigationDrawerAdapter(getActivity(), getData());
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
            @Override
            public void onClick(View view, int position) {
                drawerListener.onDrawerItemSelected(view, position);
                mDrawerLayout.closeDrawer(containerView);
            }

            @Override
            public void onLongClick(View view, int position) {

            }
        }));

        return layout;
    }


    public void setUp(int fragmentId, DrawerLayout drawerLayout, final Toolbar toolbar) {
        containerView = getActivity().findViewById(fragmentId);
        mDrawerLayout = drawerLayout;
        mDrawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
            @Override
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                getActivity().invalidateOptionsMenu();
            }

            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
                getActivity().invalidateOptionsMenu();
            }

            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
                toolbar.setAlpha(1 - slideOffset / 2);
            }
        };

        mDrawerLayout.setDrawerListener(mDrawerToggle);
        mDrawerLayout.post(new Runnable() {
            @Override
            public void run() {
                mDrawerToggle.syncState();
            }
        });

    }

    public static interface ClickListener {
        public void onClick(View view, int position);

        public void onLongClick(View view, int position);
    }

    static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {

        private GestureDetector gestureDetector;
        private ClickListener clickListener;

        public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
            this.clickListener = clickListener;
            gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return true;
                }

                @Override
                public void onLongPress(MotionEvent e) {
                    View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                    if (child != null && clickListener != null) {
                        clickListener.onLongClick(child, recyclerView.getChildPosition(child));
                    }
                }
            });
        }

        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {

            View child = rv.findChildViewUnder(e.getX(), e.getY());
            if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
                clickListener.onClick(child, rv.getChildPosition(child));
            }
            return false;
        }

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

        }


    }

    public interface FragmentDrawerListener {
        public void onDrawerItemSelected(View view, int position);
    }
}

activity_main.xml

    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:id="@+id/container_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <include
                android:id="@+id/toolbar"
                layout="@layout/toolbar" />
        </LinearLayout>

        <FrameLayout
            android:id="@+id/container_body"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />


    </LinearLayout>


    <fragment
        android:id="@+id/fragment_navigation_drawer"
        android:name="com.bicubic.botadnews.fragment.FragmentDrawer"
        android:layout_width="@dimen/nav_drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:layout="@layout/fragment_navigation_drawer"
        tools:layout="@layout/fragment_navigation_drawer" />

</android.support.v4.widget.DrawerLayout>

fragment_navigation_drawer.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

    <RelativeLayout
        android:id="@+id/nav_header_container"
        android:layout_width="match_parent"
        android:layout_height="140dp"
        android:layout_alignParentTop="true"
        android:background="@color/colorPrimary">

        <ImageView
            android:id="@+id/profile"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:layout_centerInParent="true"
            android:scaleType="fitCenter"
            android:src="@drawable/ic_profile" />

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Name"
            android:textColor="@color/white"
            android:textSize="20sp"
            android:layout_marginBottom="10dp"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true" />

    </RelativeLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/drawerList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/nav_header_container"
        android:layout_marginTop="15dp" />

</RelativeLayout>

Here is my gallery fragment

Editted GalleryFragment.java

  public class GalleryFragment extends Fragment implements View.OnClickListener {

    View rootView;
    static RecyclerView rv_video;
    RecyclerView rv_image;
    static List<File> videofiles;
    static List<File> imagefiles;
    Button bt_video, bt_image;
    private static Context context ;
    public GalleryFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_gallery, container, false);

        rv_video = (RecyclerView) rootView.findViewById(R.id.rv_video);
        rv_image = (RecyclerView) rootView.findViewById(R.id.rv_image);
        bt_video = (Button) rootView.findViewById(R.id.bt_video);
        bt_image = (Button) rootView.findViewById(R.id.bt_image);
        bt_video.setBackgroundResource(R.color.colorAccent);

        bt_video.setOnClickListener(this);
        bt_image.setOnClickListener(this);

        context = getActivity();
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
        rv_video.setLayoutManager(linearLayoutManager);
        rv_video.setHasFixedSize(true);

        LinearLayoutManager linearLayoutManager1 = new LinearLayoutManager(getActivity());
        rv_image.setLayoutManager(linearLayoutManager1);
        rv_image.setHasFixedSize(true);

        videofiles = new ArrayList<>();
        imagefiles = new ArrayList<>();
        new LoadOfflineData().execute();

        rootView.post(new Runnable() {
            @Override
            public void run() {
                new LoadOfflineData().execute();
            }
        });

        // Inflate the layout for this fragment
        return rootView;
    }

    public static class LoadOfflineData extends AsyncTask<Void, Void, Void> {

        ProgressDialog progressBar;

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

            progressBar = new ProgressDialog(context);
            progressBar.setMessage("Loading...");
            progressBar.show();
        }

        @Override
        protected Void doInBackground(Void... voids) {

            String video_path = Environment.getExternalStorageDirectory().getPath() + "/Botad News/Videos";
            Log.d("Files", "Path: " + video_path);
            File checkFile = new File(video_path);

//            videofiles = new ArrayList<>();
            File[] files = new File[0];
            if (checkFile.isDirectory()) {
                File directory = new File(video_path);
                files = directory.listFiles();

                videofiles.addAll(Arrays.asList(files));


            } else {
//                Toast.makeText(getActivity(), "Folder not Found", Toast.LENGTH_SHORT).show();
                Log.e(TAG, "doInBackground: folder not found" );
            }


            String image_path = Environment.getExternalStorageDirectory().getPath() + "/Botad News/Images";
            Log.d("Files", "Path: " + image_path);
            File checkFileImages = new File(image_path);

//            imagefiles = new ArrayList<>();
            File[] filesImage = new File[0];
            if (checkFileImages.isDirectory()) {
                File directory = new File(image_path);
                filesImage = directory.listFiles();

                imagefiles.addAll(Arrays.asList(filesImage));

            } else {
//                Toast.makeText(getActivity(), "Folder not Found", Toast.LENGTH_SHORT).show();
                Log.e(TAG, "doInBackground: folder not found" );
            }

            Log.d("Files", "Size: " + files.length);

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            progressBar.dismiss();

            if (videofiles.size() > 0) {
                RvGalleryVideoAdapter adapter = new RvGalleryVideoAdapter(videofiles, context);
                rv_video.setAdapter(adapter);
            } else {
                Toast.makeText(context, "Data not found", Toast.LENGTH_SHORT).show();
            }


        }

    }


    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

    @Override
    public void onClick(View view) {


        switch (view.getId()) {
            case R.id.bt_video:

                bt_video.setBackgroundResource(R.color.colorAccent);
                bt_image.setBackgroundResource(R.color.colorPrimary);
                rv_image.setVisibility(View.GONE);
                rv_video.setVisibility(View.VISIBLE);

                if (videofiles.size() > 0) {
                    RvGalleryVideoAdapter adapter = new RvGalleryVideoAdapter(videofiles, getActivity());
                    rv_video.setAdapter(adapter);
                } else {
                    Toast.makeText(getActivity(), "Data not found", Toast.LENGTH_SHORT).show();
                }

                break;
            case R.id.bt_image:

                bt_image.setBackgroundResource(R.color.colorAccent);
                bt_video.setBackgroundResource(R.color.colorPrimary);
                rv_image.setVisibility(View.VISIBLE);
                rv_video.setVisibility(View.GONE);

                if (imagefiles.size() > 0) {

                    RvGalleryImageAdapter adapter_image = new RvGalleryImageAdapter(imagefiles, getActivity());
                    rv_image.setAdapter(adapter_image);

                } else {
                    Toast.makeText(getActivity(), "Data not found", Toast.LENGTH_SHORT).show();

                }


                break;
            default:


                break;
        }


    }
}
Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148
Arpit Patel
  • 7,212
  • 5
  • 56
  • 67

2 Answers2

1

In your AsyncTask, you are accessing the class fields of the Fragment! This will actually block the UI Thread :-(

The lines

videofiles = new ArrayList<>();
imagefiles = new ArrayList<>();

cannot be there. You need to create local lists, put data in them and then return it in onPostExecute().

Start by replacing

public class LoadOfflineData extends AsyncTask<Void, Void, Void> {

with

public static class LoadOfflineData extends AsyncTask<Void, Void, Void> {

This will give you errors in places you need to change :-)

Kelevandos
  • 7,024
  • 2
  • 29
  • 46
  • facing same problem. And what is culprit meaning i don't know it means. – Arpit Patel Oct 27 '16 at 09:12
  • See the update. Culprit is the one who is responsible ^^ – Kelevandos Oct 27 '16 at 09:18
  • No problem, your English is much better than my Hindi :-) – Kelevandos Oct 27 '16 at 09:20
  • but when i load data in onCreatView (without using AsyncTask ) facing same problem – Arpit Patel Oct 27 '16 at 11:12
  • Exactly, that is because you are blocking the main Thread. Move the data obtaining to AsyncTask (properly) and it will not be blocked :) – Kelevandos Oct 27 '16 at 11:39
  • appreciate your effort but still same problem i added a edited GalleryFragment,java – Arpit Patel Oct 27 '16 at 12:33
  • You still have videofiles = new ArrayList<>();, you are accessing class fields. Does this code compile for you? – Kelevandos Oct 27 '16 at 12:34
  • i am putting arraylist in oncreateview but still same problem – Arpit Patel Oct 27 '16 at 12:59
  • I am sorry, but I think you do not understand the concept of concurrence :-( You are doing everything on the main Thread, so the UI gets blocked. You need to move data obtaining to another Thread (through AsyncTask) so it does not get blocked. Please read the documentation on AsyncTask and try to implement it correctly (this is a structural change, too big to provide as part of the answer) https://developer.android.com/reference/android/os/AsyncTask.html – Kelevandos Oct 27 '16 at 13:02
  • UI Thread is the main Thread of the app. Heavy work should be done on a separate Thread. There are several ways to do that, one of them is the AsyncTask. But you need to implement it correctly, you can not access class fields in it, it must be separated. – Kelevandos Oct 27 '16 at 13:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/126838/discussion-between-arpit-patel-and-kelevandos). – Arpit Patel Oct 27 '16 at 13:37
  • can i use this link as a reference?? http://androidexample.com/Thread_With_Handlers_-_Android_Example/index.php?view=article_discription&aid=58&aaid=83 – Arpit Patel Oct 27 '16 at 13:37
  • You can, but I would suggest using the AsyncTask documentation I gave you earlier – Kelevandos Oct 27 '16 at 13:52
0

I found the answer.

It is in my RecyclerAdapter when i get thumbnail using inbuilt class so it will take time to set it see my

Old code

Bitmap bmThumbnail;

//MICRO_KIND, size: 96 x 96 thumbnail
       bmThumbnail = ThumbnailUtils.createVideoThumbnail(sdcard_path + "/Botad News/Videos/" + fileName, MediaStore.Images.Thumbnails.MICRO_KIND);
        holder.img_main.setImageBitmap(bmThumbnail);

New code is using glide library so lib automatically handle the thread i assume.

 BitmapPool bitmapPool = Glide.get(context).getBitmapPool();
        int microSecond = 6000000;// 6th second as an example
        VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(microSecond);
        FileDescriptorBitmapDecoder fileDescriptorBitmapDecoder = new FileDescriptorBitmapDecoder(videoBitmapDecoder, bitmapPool, DecodeFormat.PREFER_ARGB_8888);
        Glide.with(context)
                .load(sdcard_path + "/Botad News/Videos/" + fileName)
                .asBitmap()
                .override(250,250)// Example
                .videoDecoder(fileDescriptorBitmapDecoder)
                .into(holder.img_main);

Found solution HERE....

Community
  • 1
  • 1
Arpit Patel
  • 7,212
  • 5
  • 56
  • 67