我正在使用 Parse.com android sdk。在我的内部TabsActivity.java
,我有一个SearchFragment
扩展ListFragment
,以便使用自定义 ParseQueryAdapter 填充 ListView。在我的自定义适配器中,我声明了一个自定义列表行布局,名为search_list_item.xml
. 此布局仅包含一个ParseImageView
.
我的问题是,当我快速向下滚动列表时,我的 logcat 充满了
I/dalvikvm-heap:将堆(碎片情况)增长到 ...MB 用于字节分配
并且 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 的这些文档
非常感谢您抽出宝贵的时间,并为这篇长篇文章感到抱歉,只是试图尽可能地解释一下。