我正在开发一个带有由位图填充的自定义 ListView 的应用程序。位图加载正常,但唯一的问题是每次滚动 ListView 时,都会重新加载进入视图的图像,即使它们之前已经加载过。这既浪费时间又效率低下。我想要一种获取图像一次的方法,当 ListView 将位图滚动进出视图时,它们不必重新加载。这是我的代码(只需将所有代码都放入......您正在寻找 MainAdapter 和 AsyncCaller):
public class Post extends SherlockActivity implements
PullToRefreshAttacher.OnRefreshListener, OnItemClickListener {
private PullToRefreshAttacher mPullToRefreshAttacher;
private ListView listview;
private DisplayMetrics metrics;
String[] index = { "023", "143", "564", "982", "023", "143", "564", "982",
"023", "143", "564", "982" };
String[] summary = { "One", "Two", "Three", "Four", "Five",
"Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve" };
String[] images = {
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c",
"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTpgdQYIzGWZiDsCtWIMzuZVaZABIwC-3Ym9gvGMcV5OVUdAb-c" };
ActionMode mMode;
Animation animation;
Intent i;
URL img_url;
Bitmap bmp = null;
Holder holder;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
if (Session.getActiveSession() == null) {
i = new Intent(getApplicationContext(), StartBase.class);
startActivity(i);
} else {
retrieveData();
setUpFacebook();
sessionCheck();
}
}
private void setUpFacebook() {
// TODO Auto-generated method stub
String APP_ID = getString(R.string.app_id);
FacebookRef.fb = new Facebook(APP_ID);
FacebookRef.asyncrunner = new AsyncFacebookRunner(FacebookRef.fb);
}
private void retrieveData() {
// TODO Auto-generated method stub
// Parse work: Get the data and create the list. The data has to have
// the Bitmaps
}
private void sessionCheck() {
// TODO Auto-generated method stub
Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
// Get the user's data
listview = new ListView(this);
listview.setFadingEdgeLength(0);
ArrayList<String> strings = new ArrayList<String>();
ArrayList<String> urls = new ArrayList<String>();
int pos = 0;
// As long as it is less than the number of items in the string
// array
for (int i = 0; i < summary.length; i++) {
strings.add(summary[pos]);
urls.add(images[pos]);
pos++;
}
MainAdapter mAdapter = new MainAdapter(this, strings, urls, metrics);
listview.setAdapter(mAdapter);
listview.setOnItemClickListener(this);
setContentView(listview);
pullToRefresh();
} else {
Toast.makeText(getApplicationContext(), "Please log in first",
Toast.LENGTH_LONG).show();
i = new Intent(getApplicationContext(), StartBase.class);
startActivity(i);
}
}
private void pullToRefresh() {
// TODO Auto-generated method stub
PullToRefreshAttacher.Options ptrOptions = new PullToRefreshAttacher.Options();
ptrOptions.refreshScrollDistance = 0.6f;
ptrOptions.headerLayout = R.layout.customised_header;
ptrOptions.headerTransformer = new CustomisedHeaderTransformer();
mPullToRefreshAttacher = PullToRefreshAttacher.get(this, ptrOptions);
PullToRefreshAttacher.ViewDelegate handler = new AbsListViewDelegate();
mPullToRefreshAttacher.addRefreshableView(listview, handler, this);
}
@Override
public void onRefreshStarted(View view) {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "Works",
Toast.LENGTH_LONG).show();
new AsyncCaller().execute();
}
}).start();
// Notify PullToRefreshAttacher that the refresh has finished
mPullToRefreshAttacher.setRefreshComplete();
}
static class CustomisedHeaderTransformer extends
PullToRefreshAttacher.HeaderTransformer {
private View mHeaderView;
private TextView mMainTextView;
private TextView mProgressTextView;
@Override
public void onViewCreated(Activity activity, View headerView) {
mHeaderView = headerView;
mMainTextView = (TextView) headerView.findViewById(R.id.ptr_text);
mProgressTextView = (TextView) headerView
.findViewById(R.id.ptr_text_secondary);
}
@Override
public void onReset() {
mMainTextView.setVisibility(View.VISIBLE);
mMainTextView.setText(R.string.pull_to_refresh_pull_label);
mProgressTextView.setVisibility(View.GONE);
mProgressTextView.setText("");
}
@Override
public void onPulled(float percentagePulled) {
mProgressTextView.setVisibility(View.VISIBLE);
mProgressTextView
.setText(Math.round(100f * percentagePulled) + "%");
}
@Override
public void onRefreshStarted() {
mMainTextView.setText(R.string.pull_to_refresh_refreshing_label);
mProgressTextView.setVisibility(View.GONE);
}
@Override
public void onReleaseToRefresh() {
mMainTextView.setText(R.string.pull_to_refresh_release_label);
}
@Override
public void onRefreshMinimized() {
// In this header transformer, we will ignore this call
}
@Override
public boolean showHeaderView() {
final boolean changeVis = mHeaderView.getVisibility() != View.VISIBLE;
if (changeVis) {
mHeaderView.setVisibility(View.VISIBLE);
}
return changeVis;
}
@Override
public boolean hideHeaderView() {
final boolean changeVis = mHeaderView.getVisibility() != View.GONE;
if (changeVis) {
mHeaderView.setVisibility(View.GONE);
}
return changeVis;
}
}
@Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
com.actionbarsherlock.view.SubMenu subMenu1 = menu
.addSubMenu("Categories");
subMenu1.add(0, 1, Menu.NONE, "Entertainment");
subMenu1.add(0, 2, Menu.NONE, "Fashion");
subMenu1.add(0, 3, Menu.NONE, "Business");
subMenu1.add(0, 4, Menu.NONE, "Books");
subMenu1.add(0, 5, Menu.NONE, "Kids");
subMenu1.add(0, 6, Menu.NONE, "Home");
com.actionbarsherlock.view.MenuItem subMenu1Item = subMenu1.getItem();
subMenu1Item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(
com.actionbarsherlock.view.MenuItem item) {
switch (item.getItemId()) {
case 1:
Toast.makeText(getApplicationContext(), item.getTitle(),
Toast.LENGTH_LONG).show();
break;
case 2:
Toast.makeText(getApplicationContext(), item.getTitle(),
Toast.LENGTH_LONG).show();
break;
case 3:
Toast.makeText(getApplicationContext(), item.getTitle(),
Toast.LENGTH_LONG).show();
break;
case 4:
Toast.makeText(getApplicationContext(), item.getTitle(),
Toast.LENGTH_LONG).show();
break;
case 5:
Toast.makeText(getApplicationContext(), item.getTitle(),
Toast.LENGTH_LONG).show();
break;
case 6:
Toast.makeText(getApplicationContext(), item.getTitle(),
Toast.LENGTH_LONG).show();
break;
case R.id.action_account:
i = new Intent(getApplicationContext(), Account.class);
startActivity(i);
break;
case R.id.action_logout:
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("Logout?");
alertDialog.setMessage("Are you sure you want to logout?");
alertDialog.setIcon(android.R.drawable.ic_lock_power_off);
alertDialog.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(), "Logout",
Toast.LENGTH_LONG).show();
Session.getActiveSession()
.closeAndClearTokenInformation();
i = new Intent(getApplicationContext(),
StartBase.class);
startActivity(i);
}
});
alertDialog.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
break;
}
return super.onOptionsItemSelected(item);
}
private class Holder {
public TextView textview;
public ImageView imageView;
}
public class MainAdapter extends ArrayAdapter<String> {
private Context context;
private LayoutInflater mInflater;
private ArrayList<String> strings;
private ArrayList<String> urls;
private DisplayMetrics metrics_;
public MainAdapter(Context context, ArrayList<String> strings,
ArrayList<String> urls, DisplayMetrics metrics) {
super(context, 0, strings);
this.context = context;
this.mInflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.strings = strings;
this.urls = urls;
this.metrics_ = metrics;
}
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
final String str = this.strings.get(position);
final String url = this.urls.get(position);
if (convertView == null) {
convertView = mInflater
.inflate(R.layout.custom_list_item, null);
holder = new Holder();
holder.textview = (TextView) convertView
.findViewById(R.id.text);
holder.textview.setTextColor(0xFFFFFFFF);
holder.imageView = (ImageView) convertView
.findViewById(R.id.pic);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
try {
img_url = new URL(url);
holder.imageView.setBackgroundResource(R.drawable.logo);
new AsyncCaller().execute();
holder.textview.setText(str);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
animation = AnimationUtils.loadAnimation(context,
R.anim.push_left_in);
animation.setDuration(200);
convertView.startAnimation(animation);
animation = null;
return convertView;
}
}
private class AsyncCaller extends AsyncTask<Void, Void, Void> {
ProgressDialog pdLoading = new ProgressDialog(Post.this);
@Override
protected void onPreExecute() {
super.onPreExecute();
pdLoading.setMessage("Loading...");
pdLoading.show();
}
@Override
protected Void doInBackground(Void... params) {
try {
bmp = BitmapFactory.decodeStream(img_url.openConnection()
.getInputStream());
bmp = RoundBitmap.roundCorner(bmp, 20);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
holder.imageView.setImageBitmap(bmp);
pdLoading.dismiss();
}
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "List item selected",
Toast.LENGTH_LONG).show();
i = new Intent(getApplicationContext(), AdDetails.class);
Bundle b = new Bundle();
b.putString("index", index[arg2]);
b.putString("summary", summary[arg2]);
b.putString("url", images[arg2]);
i.putExtras(b);
startActivity(i);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("Leave?");
alertDialog.setMessage("Are you sure you want to leave?");
alertDialog.setIcon(android.R.drawable.ic_lock_power_off);
alertDialog.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
android.os.Process.killProcess(android.os.Process
.myPid());
}
});
alertDialog.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
return super.onKeyDown(keyCode, event);
}
}