1

我正在开发一个带有由位图填充的自定义 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);
}

  }
4

3 回答 3

1

简单的方法——使用毕加索(http://square.github.io/picasso/

于 2013-10-17T13:43:28.773 回答
1

Android 开发者文档中有一个很好的培训指南

于 2013-10-17T13:49:39.577 回答
0

我可能对此有误,但我认为问题在于,当您滚动应用程序时,它会认为它正在经历某种配置更改。根据我最近编写线程进程的经验,在旋转屏幕时,我不希望重新启动下载或重新加载某些对象。在那里硬编码的文件仍然使用他们的 ID,但其他文件被重新下载。

解决方案是使用两种方法,一种识别何时发生配置更改,然后获取所需的对象并将它们传递给弱引用,然后另一种询问我们是否刚刚来自配置更改以及是否加载这些对象来自它们的弱引用。

于 2013-10-17T13:50:30.073 回答