java - ViewPager.setAdapter 需要 200 毫秒到 300 毫秒才能执行

标签 java android android-fragments android-asynctask

我的 ViewPager 有一点 UI 问题。

我的 ViewPager 是我的 UI 的中心。

我有一个包含 4 个项目的 NavigationView 和一个包含 2 个项目的工具栏。

每次单击 NavigationView 的项目时,我都会更换适配器。因此我有 4 个适配器,只有一个导致问题:BrowseAdapter(代码如下)。

此适配器充满了事件列表,并为每个事件提供了一个 fragment 。

值得一提的是,无论 eventList 的大小如何,ViewPager 的 setAdapter 方法至少需要 150ms 才能执行,而对于其他 Adapters,加载只需 20 到 50ms。

我试图将所有对 setAdapter 的调用都放在 View.post(new Runnable()); 中方法和 AsyncTask<Void, Void, Void> :

  • post 方法卡住了 UI

  • AsyncTask 没有任何改变,因为我只能在 UI 线程上调用 setAdapter(在 postExecute 方法中),这与在没有 AsyncTask 的情况下调用它基本相同。

我认为这基本上是一个优化问题,但我看不出问题出在哪里。

谢谢你的帮助。

这里是有问题的代码:

主要 Activity :

/*
.
. Import stuff
.
.
.*/

public class MainActivity extends AppCompatActivity implements RequestCallback,
ConnectionCallbacks, OnConnectionFailedListener, FBLoginChanged, LocationListener {


/**
 * The main content view
 */
private CustomViewPager mViewPager;

/**
 * Adapters : One for each feature of the application
 */
private BrowseAdapter mBrowseAdapter;
private CurrentAdapter mCurrentAdapter = new CurrentAdapter(getFragmentManager());
private CalendarAdapter mCalendarAdapter = new CalendarAdapter(getFragmentManager());
private SettingsAdapter mSettingsAdapter = new SettingsAdapter(getFragmentManager());

/**
 * The action bar of the application
 */
private Toolbar mToolbar;
/**
 * TabLayout provide the new Material Design tab navigation
 */
private TabLayout mTabLayout;
/**
 * Side navigation given by a NavigationView instead of a NavigationDrawer
 * to support Material Design
 */
private NavigationView mNavigationView;
private DrawerLayout mDrawerLayout;

/**
 * List of all events.
 */
private ArrayList<Event> mEventList = new ArrayList<Event>();

/**
 * Provide different way of browsing through the events
 */
private enum BrowseType {
    DEFAULT,
    POPULAR,
    RANDOM
}

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


    /*.
    .
    . Initialization stuff
    .
    .*/

    //Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
    mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {

        // This method will trigger on item Click of navigation menu
        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem) {

            //Closing drawer on item click
            mDrawerLayout.closeDrawers();

            //Check to see which item was being clicked and perform appropriate action
            switch (menuItem.getItemId()){
            case R.id.home:
                mTabLayout.setVisibility(View.VISIBLE);
                mBrowseAdapter.setBrowsingType(BrowseType.DEFAULT);
                mViewPager.setAdapter(mBrowseAdapter);
                break;
            case R.id.favs:
                mTabLayout.setVisibility(View.GONE);
                mViewPager.setAdapter(mCurrentAdapter);
                break;
            case R.id.calendar:
                mTabLayout.setVisibility(View.GONE);
                mViewPager.setAdapter(mCalendarAdapter);
                break;
            case R.id.setting:
                mTabLayout.setVisibility(View.GONE);
                mViewPager.setAdapter(mSettingsAdapter);
                break;
            default:
                break;
            }

            return true;
        }
    });

    mViewPager = (CustomViewPager) findViewById(R.id.pager);

    mBrowseAdapter = new BrowseAdapter(this.getFragmentManager(), mEventList);

    mTabLayout.setOnTabSelectedListener(new OnTabSelectedListener() {

        @Override
        // Unused
        public void onTabReselected(Tab tab) {

        }

        @Override
        public void onTabSelected(Tab tab) {
            switch(tab.getPosition()) {
            case 0:
                mBrowseAdapter.setBrowsingType(BrowseType.DEFAULT);
                break;
            case 1: 
                mBrowseAdapter.setBrowsingType(BrowseType.POPULAR);
                break;
            default: // Unused
                break;
            }
            mViewPager.setAdapter(mBrowseAdapter);
        }
        @Override
        // Unused
        public void onTabUnselected(Tab tab) {

        }

    });

    mViewPager.setAdapter(mBrowseAdapter);
}

}

我的适配器:

private class BrowseAdapter extends FragmentStatePagerAdapter {

private ArrayList<Event> eventList = new ArrayList<Event>();
private BrowseType browseType = BrowseType.DEFAULT;
private HashMap<Integer, EventFragment> fragmentReferenceMap = new HashMap<Integer, EventFragment>();

public BrowseAdapter(FragmentManager fragmentManager,
        ArrayList<Event> mEventList) {
    super(fragmentManager);
}

public void setBrowsingType(BrowseType type) {
    this.browseType = type;
    this.commitChanges();
}

public Event getEventById(int id) {
    for(Event event : eventList) {
        if(event.getId() == id)
            return event;
    }
    return null;
}

public void setJSONData(JSONArray jsonArray) {
    for (int i = 0; i < jsonArray.length(); i++) {
        try {
            JSONObject obj = jsonArray.getJSONObject(i);
            Event event = new Event();
            event.setId(obj.getInt("id"));
            event.setName(obj.getString("name"));
            event.setShort_description(obj.getString("short_desc"));
            event.setLong_description(obj.getString("long_desc"));
            event.setPlace(obj.getString("place").split(";")[0]);
            Location loc = new Location("");
            loc.setLatitude(Double.valueOf(obj.getString("place")
                    .split(";")[1]));
            loc.setLongitude(Double.valueOf(obj.getString("place")
                    .split(";")[2]));
            event.setLocation(loc);
            event.setDate(obj.getString("date"));
            eventList.add(event);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

public String getJSONData() {
    JSONArray toReturn = new JSONArray();
    for (Event event : eventList) {
        JSONObject tmp = new JSONObject();
        try {
            tmp.put("name", event.getName());
            tmp.put("short_desc", event.getShort_description());
            tmp.put("long_desc", event.getLong_description());
            tmp.put("id", event.getId());
            tmp.put("date", event.getDate());
            tmp.put("place",
                    event.getPlace()
                    + ";"
                    + String.valueOf(event.getLocation()
                            .getLatitude())
                            + ";"
                            + String.valueOf(event.getLocation()
                                    .getLongitude()));
            toReturn.put(tmp);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    return toReturn.toString();
}

public boolean addItem(Event item) {
    return eventList.add(item);
}

@SuppressWarnings("unused")
public Event removeAt(int position) {
    return eventList.remove(position);
}

public void commitChanges() {
    this.sort();
    this.notifyDataSetChanged();
}

private void sort() {
    Log.d("SORT", browseType.name());
    Collections.sort(eventList, new Comparator<Event>() {
        @Override
        public int compare(Event arg0, Event arg1) {
            float dis1 = arg0.getLocation().distanceTo(
                    LocationProvidor.getInstance().getLastLocation());
            float dis2 = arg1.getLocation().distanceTo(
                    LocationProvidor.getInstance().getLastLocation());
            int userNumber1 = Integer.parseInt(arg0.getUserNumber());
            int userNumber2 = Integer.parseInt(arg1.getUserNumber());
            switch(browseType) {
            case DEFAULT:
                return (int) (dis1 - dis2);
            case POPULAR:
                return userNumber2 - userNumber1;
            case RANDOM:
                return new Random().nextInt();
            default:
                return 0;
            }
        }

    });
}

public void empty() {
    eventList.clear();
}

@Override
public EventFragment getItem(int position) {
    EventFragment frag = EventFragment.newInstance(eventList.get(position));
    frag.setIsCurrents(mCurrentAdapter.containsEventId(eventList.get(position).getId()));
    fragmentReferenceMap.put(position, frag);
    return frag;
}

@Override
public void destroyItem(View container, int position, Object object) {
    super.destroyItem(container, position, object);
    fragmentReferenceMap.remove(position);
    Log.d("fr.blopper.app", "destroy " + position);
}

public EventFragment getFragment(int position) {
    return fragmentReferenceMap.get(position);
}

@Override
public int getCount() {
    return eventList.size();
}
}

和 CustomViewPager(我创建它只是为了测量 setAdapter 所花费的时间):

import android.content.Context;
import android.util.AttributeSet;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.support.v4.view.PagerAdapter;


public class CustomViewPager extends ViewPager {

public CustomViewPager(Context c) {
    super(c);
}

public CustomViewPager(Context c, AttributeSet as) {
    super(c, as);
}

@Override
public void setAdapter(PagerAdapter adapter) {
    long start = System.currentTimeMillis();
    super.setAdapter(adapter);
    Log.d("TAG", "Custom time " + (System.currentTimeMillis() - start));
}
}

最佳答案

找到答案了,跟ViewPager没有关系。

适配器提供的 fragment 正在调用响应缓慢的 Google API。

关于java - ViewPager.setAdapter 需要 200 毫秒到 300 毫秒才能执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34480311/

相关文章:

android - 管理 fragment ,公共(public)静态 viewpager

java - 如何从 Fragment Dialog 更新自定义 RecyclerView?

java - 每个具有单个抽象方法的接口(interface)都应该是函数式接口(interface)吗?

java - 使用 Apache Camel 如何解码通过 CXF 端点传入的反序列化对象?

java - 这个递归函数有什么作用?

android - 如何删除使用 ACTION_VIDEO_CAPTURE 的 Intent 录制的视频?

Java 四舍五入 0.05 钱

java - 填充Listview时Arraylist和Hashmap的问题

android - 是否可以将新的APK自动上传到Google Play?

android - ViewPager中如何不刷新页面