离线数据加载时导航抽屉卡住

时间:2016-10-27 07:22:52

标签: android android-fragments material-design navigation-drawer

我正在开发新闻app用户可以下载视频和图像。

所以我开发了带有材料设计的不同片段的导航抽屉。但是当我点击图库(我显示下载的视频和图像)时,我会遇到一些问题,它会停留一段时间,然后打开片段。它只发生在特定的片段中,但不是全部。

请参阅Video here

这是我的代码:

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>

这是我的图库片段

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


    }
}

2 个答案:

答案 0 :(得分:1)

AsyncTask中,您正在访问片段的类字段!这实际上会阻止UI线程: - (

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

不能在那里。您需要创建本地列表,将数据放入其中,然后在onPostExecute()中返回。

首先替换

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

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

这会在您需要更改的地方出现错误:-)

答案 1 :(得分:0)

我找到了答案。

当我使用内置类获取缩略图时,它在我的RecyclerAdapter中,所以设置它需要时间看我的

旧代码

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

新代码正在使用滑动库,因此lib会自动处理我假设的线程。

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

找到解决方案HERE....