前面一直提到了List是用来显示数据了,实际当中数据不可能就只有几条,可能有成百上千条。但是问题出现了,由于手机的内存比较小,处理数据的能力不强,如果有上百条的数据,加载这些数据的时候,如果一次性加载,画面可能会卡在那里,就算你做一个画面来显示等待页面,但是用户不希望他等了很久才看到数据。这个问题,我们该如何解决呢?
我的解决方案是:这些数据并不一定要一次性加载,因为手机屏幕就那么大,也许整屏连10条数据都显示不了,我们就可以先只加载10条数据,在List的末尾加上一个“More”按钮,当用户浏览完那些数据时,点击”More”按钮就再加载10条数据,保持More按钮始终在List的结尾处。
有了前面的基础,我们实现起这些也并不难,只要按照自己的思路,一步一步写下来还是很容易的。
import com.sun.lwuit.Button; import com.sun.lwuit.Component; import com.sun.lwuit.Container; import com.sun.lwuit.Form; import com.sun.lwuit.Image; import com.sun.lwuit.Label; import com.sun.lwuit.List; import com.sun.lwuit.events.ActionEvent; import com.sun.lwuit.events.ActionListener; import com.sun.lwuit.layouts.BorderLayout; import com.sun.lwuit.layouts.BoxLayout; import com.sun.lwuit.list.ListCellRenderer; import com.sun.lwuit.plaf.Border; import com.sun.lwuit.util.Resources; import java.io.IOException; /** * * @author Sunny */ public class ListForm extends Form { //start用来标识每条数据,模拟数据时以辨别每条数据不同 private static int start = 0; private Button more = new Button("More"); private List personList; public ListForm() { setLayout(new BoxLayout(BoxLayout.Y_AXIS)); Person[] persons = getPersons(); personList = createList(persons, List.VERTICAL, new Renderer()); personList.setIgnoreFocusComponentWhenUnfocused(true); addComponent(personList); addComponent(more); more.addActionListener(new ButtonActionListener()); } //More按钮的事件 private class ButtonActionListener implements ActionListener { public void actionPerformed(ActionEvent evt) { new Thread(new LoadData()).start(); } } class LoadData implements Runnable { public void run() { //在setLoading和removeLoading方法中间加载数据,同时会有一个loading.gif的 //动画效果,加载开始时显示,加载结束后动画效果消失。 setLoading(more); addListData(); removeLoading(more); } public void addListData() { Person[] persons = getPersons(); for (int i = 0; i < persons.length; i++) { personList.addItem(persons[i]); } //当时以为要重新设置ListCellRenderer,再开始理解MVC之后,就知道这句是多余的。ListCellRenderer是控制器 //personList.setListCellRenderer(new Renderer()); ListForm.this.setFocused(personList); //关键的一句,像List中添加数据时,需要对Form重新进行验证,重新进行验证,Form窗体会重画 ListForm.this.revalidate(); } } /** * 点击按钮时设置loading动画效果 */ public void setLoading(Button b) { try { Image loading_icon = Resources.open("/resources2.res").getImage("loading.gif"); b.setIcon(loading_icon); b.setTextPosition(Button.RIGHT); } catch (IOException ex) { ex.printStackTrace(); } } /** * 移除按钮loading动画效果 */ public void removeLoading(Button b) { b.setIcon(null); } /** * 这里每次取10条数据,模拟数据。 * @return */ public Person[] getPersons() { Person[] personArray = new Person[10]; Image photo = null; try { photo = Image.createImage("/smallphoto.jpg"); } catch (IOException ex) { ex.printStackTrace(); } for (int i = 0; i < personArray.length; i++) { personArray[i] = new Person("Sunny Peng" + (++start), photo); } return personArray; } /** * Model */ class Person { private String name; private Image photo; public Person(String name, Image photo) { this.name = name; this.photo = photo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Image getPhoto() { return photo; } public void setPhoto(Image photo) { this.photo = photo; } } /** * View */ private List createList(Person[] persons, int orientation, ListCellRenderer renderer) { List list = new List(persons); list.setListCellRenderer(renderer); list.setOrientation(orientation); return list; } /** * Controller */ class Renderer extends Container implements ListCellRenderer { public Label name = new Label(""); public Label pic = new Label(""); public Label focus = new Label(""); public Container cnt = new Container(new BoxLayout(BoxLayout.Y_AXIS)); public Renderer() { setLayout(new BorderLayout()); addComponent(BorderLayout.WEST, pic); name.getStyle().setBgTransparency(0); cnt.addComponent(name); addComponent(BorderLayout.CENTER, cnt); //focus用于设置List选中时的效果,这里设置List的选中项具有绿色的边框 focus.getStyle().setBorder(Border.createLineBorder(1, 0x00ff00)); } public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) { Person person = (Person) value; name.setText(person.getName()); pic.setIcon(person.getPhoto()); return this; } public Component getListFocusComponent(List list) { return focus; } } }
注意:我这里只有一个List和一个Button,如果组件很多,比如再加一个搜索框和搜索按钮,那就得在代码中加上上一节解决List获得焦点时Form自动向下滚的Bug。在代码中,addListData()方法是用来给List添加数据的。
代码写完了,我们总要看看效果,以下是我做的粗糙的Demo的效果图(代码中是以10个一组,图片中是以5个一组)。
点击按钮前:
点击按钮时,注意More有效果:
数据加载完毕后: