gpt4 book ai didi

android - 在快速滚动时使用自定义 ParseQueryAdapter 在 ListView fragment 上增加堆( fragment 大小写)

转载 作者:行者123 更新时间:2023-11-29 21:00:06 27 4
gpt4 key购买 nike

我正在使用 Parse.com android sdk。在我的 TabsActivity.java 中,我有一个 SearchFragment,它扩展了 ListFragment,以便使用自定义 ParseQueryAdapter 填充 ListView。在我的自定义适配器中,我声明了一个名为 search_list_item.xml 的自定义列表行布局。此布局仅包含一个 ParseImageView

我的问题是,当我快速向下滚动列表时,我的 logcat 满了

I/dalvikvm-heap﹕ Grow heap (frag case) to ...MB for byte allocation

并且 listView 返回到初始位置(这意味着它返回到第一个项目)。另一方面,如果我慢慢滚动列表,我可以在没有这个错误的情况下到达项目的末尾。我该如何解决这个问题??

此外,如果我使用默认的 ParseQueryAdapter 而没有使用 search_list_item.xml 自定义行,我不会遇到这样的问题。

下面我贴一些我认为有用的代码:

search_list_item.xml的代码

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<com.parse.ParseImageView
android:id="@+id/ProfileImage"
android:layout_width="match_parent"
android:layout_height="wrap_content" />



</RelativeLayout>

TabsActivity.Java的代码

public class TabsActivity extends Activity implements SearchFragment.OnFragmentInteractionListener, ActionBar.TabListener {

/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link android.support.v13.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;

/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;

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

// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setLogo(R.drawable.logo_white);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());

// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.tabs_pager);
mViewPager.setAdapter(mSectionsPagerAdapter);

// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});

// For each of the sections in the app, add a tab to the action bar.

actionBar.addTab(
actionBar.newTab()
.setText("Search")
.setTabListener(this));

actionBar.addTab(
actionBar.newTab()
.setText("Secind")
.setTabListener(this));

actionBar.addTab(
actionBar.newTab()
.setText("Third")
.setTabListener(this)
);

actionBar.addTab(
actionBar.newTab()
.setText("Fourth")
.setTabListener(this));


}


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

}
return super.onOptionsItemSelected(item);
}

@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}

@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}

/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/wizard1.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {

public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}


@Override
public Fragment getItem(int index) {

switch (index) {
case 0:
// Search fragment activity
return new SearchFragment();
case 1:
// Flirts fragment activity
return new SecondFragment();
case 2:
// Explore fragment activity
return new ThirdFragment();
case 3:
//Profile fragment activity
return new FourthFragment();
}

return null;
}


@Override
public int getCount() {
// Show 4 total wizard1.
return 4;
}

}


public void onFragmentInteraction(String id) {
// The user selected the headline of an article from the HeadlinesFragment
// Do something here to display that article
}

}

SearchFragment.java

代码
public class SearchFragment extends ListFragment {

private OnFragmentInteractionListener mListener;
private CustomDogAdapter mainAdapter;

/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public SearchFragment() {
}

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


mainAdapter = new CustomAdapter(this.getActivity());


// Set the ListActivity's adapter to be the PQA
mainAdapter.setAutoload(false);
mainAdapter.loadObjects();
setListAdapter(mainAdapter);


}



@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}

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


@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);

if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
}
}

/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(String id);
}



}

CustomAdapter.java的代码

public class CustomAdapter extends ParseQueryAdapter<ParseObject> {

public CustomAdapter(Context context) {
// Use the QueryFactory to construct a PQA that will only show
// Todos marked as high-pri
super(context, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery create() {
ParseQuery query = new ParseQuery("Photo");
query.whereEqualTo("imageName", "profileImage");
// query.setCachePolicy(ParseQuery.CachePolicy.CACHE_ELSE_NETWORK);
return query;
}
});
}

// Customize the layout by overriding getItemView
@Override
public View getItemView(ParseObject object, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.search_list_item, null);
}

super.getItemView(object, v, parent);

// Add and download the image
ParseImageView image = (ParseImageView) v.findViewById(R.id.profileImage);
ParseFile photoFile = object.getParseFile("imageFile");
if (photoFile != null) {
image.setParseFile(photoFile);
image.loadInBackground();
// (new GetDataCallback() {
// @Override
// public void done(byte[] data, ParseException e) {
// // nothing to do
// }
// });

}


// // Add the title view
// TextView titleTextView = (TextView) v.findViewById(R.id.text1);
// titleTextView.setText(object.getString("title"));
//
// // Add a reminder of how long this item has been outstanding
// TextView timestampView = (TextView) v.findViewById(R.id.timestamp);
// timestampView.setText(object.getCreatedAt().toString());
return v;
}

}

我研究了很多次并遵循了 Parse.com 上的这些文档

1) UI-ParseQueryAdapter

2) MealSpotting

非常感谢您抽出宝贵的时间,也很抱歉发了这么长的帖子,只是尽量解释清楚。

最佳答案

在对 abot ListView 及其性能进行了一些更一般的搜索之后,我浏览了一篇博客文章,其中有一段非常有趣的最后一段说:

Never set the height of a ListView to wrap_content. If you have all your data locally available, it might not seem so bad, but it becomes particularly troublesome when you don’t. If you use wrap_content on your ListView, this is what happens: The first getView call is done, convertView is null, and position 0 is loaded. Now, position 1 is loaded, but it is passed the View you just generated for position 0 as its convertView. Then position 2 is loaded with that same View, and so on. This is done to lay out the ListView since it has to figure out how tall it should be and you didn’t explicitly tell it. Once it has run through all of those positions, that View is passed back to position 0 for yet another getView call, and then position 1 and on are loaded with getView and no convertView. You’re going to end up seeing getView called two or three times as often as you would have expected. Not only does that suck for performance, but you can get some really confusing issues.

来源:Read the last paragraph

我不完全理解它,因为我是开发新手,但在阅读之后我决定使用预定义的 dp 值更改布局高度和宽度并设置 android:scaleType="centerCrop"。这解决了堆增长问题,滚动变得非常流畅。

我希望有人像我一样发现它有帮助,如果有人能从技术上更详细地解释它,我将非常有兴趣阅读它。非常感谢您!

关于android - 在快速滚动时使用自定义 ParseQueryAdapter 在 ListView fragment 上增加堆( fragment 大小写),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26364374/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com