片段导航抽屉关闭不顺畅

时间:2016-12-21 19:48:48

标签: android android-fragments navigation-drawer

我为我的应用实施了Navigation Drawer,大部分都能正常使用。

我的Home标签会显示一些API请求以显示一些信息,这些请求及其所需的工作量(即使它是相当小的)阻止抽屉中途关闭,使其不顺畅

我的第一个"解决方案"是to load the fragment only after the Drawer closes,就像这样:

toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {

        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);

            displaySelectedScreen(itemSelected.getItemId());
        }
    };

但是这会在Fragments视图显示之前创建一个0.5秒的等待,从用户的角度来看,这不是很合适。

以下是我activity_main.xml的一部分:

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer" />

这是我到目前为止显示Fragment的方式:

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(final MenuItem item) {      
    displaySelectedScreen(item.getItemId());
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

以下是displaySelectedScreen中发生的事情:

private void displaySelectedScreen(int itemId) {
    Fragment fragment;
    fragment = checkFragment(itemId); // Instantiates the right Fragment

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.content_frame, fragment);
    ft.commit();

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

    // Close our Drawer since we have selected a valid item.
    drawer.closeDrawer(GravityCompat.START);
}

您建议Navigation Drawer顺利关闭哪些内容?

修改

根据要求,以下是我的AsyncTask代码,该代码执行API请求并返回JSONObject

/**
 * Requests information from the API via APIRequests
 * Extends AsyncTask in order to do network-related actions in background.
 */
private class SearchInfo extends AsyncTask<Void, Integer, JSONObject> {

    @Override
    protected JSONObject doInBackground(Void... params) {
        JSONObject information;

        APIRequests apiRequests = new APIRequests();
        information = apiRequests.getGameInfo();

        requestDone = true;

        return information;
    }
}

APIRequest方法通过HTTP GET执行简单HttpURLConnection,并返回JSONObject并检索数据。

4 个答案:

答案 0 :(得分:3)

在抽屉关闭之前,您似乎在displaySelectedScreen()中提交了Fragment

@Override
public boolean onNavigationItemSelected(final MenuItem item) {      
    displaySelectedScreen(item.getItemId()); // Commit is there
    drawer.closeDrawer(GravityCompat.START); // And drawer closing simultaneously
    return true;
}

我该怎么做

// Create a field that marks that something needs to be displayed
// after drawer closes. When null means no action (drawer closed
// by the user, not by selecting an item)
Integer itemIdWhenClosed;

@Override
public boolean onNavigationItemSelected(final MenuItem item) {      
    itemIdWhenClosed = item.getItemId(); // Mark action when closed
    drawer.closeDrawer(GravityCompat.START); // Close it
    return true;
}

@Override
public void onDrawerClosed(View view) {
    super.onDrawerClosed(view);
    // If id to show is marked, perform action
    if (itemIdWhenClosed != null) {
        displaySelectedScreen(itemIdWhenClosed);
        // Reset value
        itemIdWhenClosed = null;
    }
}

// Now here just commit, don't close the drawer since this is already
// fired when it's closed
private void displaySelectedScreen(int itemId) {
    final Fragment fragment = checkFragment(itemId);
    final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.content_frame, fragment);
    ft.commit();
}

答案 1 :(得分:0)

您是否在没有提出API请求的情况下尝试,并查看问题是否在片段的显示上?

答案 2 :(得分:0)

确保您使用其他线程来执行API请求。您可以使用AsyncTaskLoadersServicesIntentServices等,具体取决于具体的API请求是。这样,Fragment可以立即显示,并且数据可以在加载时添加到其中

答案 3 :(得分:0)

我使用的解决方案如下:

由于我显示的数据不会经常更改(至少每天都不会更改),因此我现在只在我的应用的每个会话(流程)中执行一次API请求。

 if (!requestDone) { // Where requestDone == true when I have done an API request
      getGameInfo();
 }

仅在尚未实例化时才实例化片段(为了保持requestDone的值)。

动画现在始终流畅(因为我的启动画面在API请求完成时结束)。

现在我很明显,请求的时间数量必须等于更新的概率。