在做一个android文本阅览器时遇到的问题及解决办法

来源:互联网 发布:查看网络打印机端口ne 编辑:程序博客网 时间:2024/05/16 07:25

几个星期前应我妹的要求(其实这个要求在经过再次的baidu后她很快就解决了- -#),我花了一段时间做了一个Android的文本阅览器,主要的作用就是在Android上阅读TXT文本文档。虽然我以前几乎没怎么做过Java的应用,不过就我用了这么多VB、C#以及其他语言的应用的经历,我相信不会很难而且我给自己下的时限是两个星期(最后的结果再次证明了一个事实,在软件的世界中,即使一个很小的应用也不要高估自己的速度,特别是在自己对这个系统还没有很好的了解的情况下)。最后,我妹还是很积极地帮我测试了一下。结果,还没进入主题就出了一个大bug:ListView在滚屏时不断重复第一屏。内事不决问百度,百度后我找到了解决方法,但是还是没有了解为什么会出现这个问题。一下是我的源代码和解决办法:

主要是把原来的创建adapter的方法由(这个方法也是由网上找来的,这又验证了拷贝的东西总是存在风险):

private View makeItemView(String strText, int resId) {

      // 使用View的对象itemView与R.layout.item关联   
     View itemView = inflater.inflate(R.layout.item, null);   
      // 通过findViewById()方法实例R.layout.item内各组件     
      TextView text = (TextView) itemView.findViewById(R.id.itemName);   
      ImageView image = (ImageView) itemView.findViewById(R.id.itemImage);  
      text.setText(strText);
      image.setImageResource(resId);  
      return itemView; 

}

 

改为:

public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            final LayoutInflater inflater = (LayoutInflater) mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.item, null);
            holder = new ViewHolder();
            holder.icon = (ImageView) convertView.findViewById(R.id.itemImage);
            holder.text = (TextView) convertView.findViewById(R.id.itemName);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.icon.setImageResource(mimageData[position]);
        holder.text.setText(mtextData[position]);
        return convertView;
    }

 

改后的方法是Google I/O推荐的方法,我照着改了,确实解决了问题,但是为什么会出现那个问题呢?http://edu.gamfe.com/tutor/d/30509.html 给出了解释,但是我看不懂,有哪位不小心看到这篇博客的,能指点指点不?

 

第二个问题是,在看中文书时换页后会有出现乱码的情况发生。这个我知道为什么。因为我把每页显示的字节数限定为5000。这样,由于中文GB2312是两个字节的编码,而ASCII是一个字节的编码,在一页上不全是GB2312,也有ASCII,就会出现到页边界的时候一个GB2312编码被分到两页中显示。而在第二页开始的那个下半字节就被当成上半字节和另一个编码的上半字节编在一起成为一个中文字。GB2312就这样恶心,如果大家都用utf-8,这个世界就安静了(这是百度GB2312得到的话- -#)。很郁闷,GB2312的上半字节和下半字节在编码上几乎是重叠的(上半从A0开始,下半从A1开始,而utf-8的第一个字节总是以0B11开始,所有其后的字节都是以0B10开始,这样就很容易知道是不是被分裂了),没法知道分页后的第一个字节是不是所要汉字的第一个字节。

当然,还是被我找到了方法,虽然方法有点恶心,不是很完美的解决办法,但是阅读网上流传的大部分文章还是可以的。我是在一个网页上了解到GB2312编码分成了几个区,其中一级汉字区为第一字节从0xB1~0xD7。大家一定都想到了,网上的书,当然用的主要都是一级汉字,有多少人会去用那些读都读不出来的的生僻字呢(火星文除外,该阅读器不适宜于90后- -!)?所以我就用了如下的程序解决了这个问题:

 

if(encoding.equals("GB2312"))
   {
    txtFile.seek(page * bytesofeachpage - 4);

 

    //这里是重点,从文本中读出16个字节待用。主要的目的是看处于0xB1~0xD7之间的数在奇数位得多还是偶数位的多。在最好的情况

    //下(也就是全是一级汉字),odd和even中会有一个是8
    byte[] temp = new byte[16];
    txtFile.read(temp, 0, 16);
    int odd = 0, even = 0;
    for(int i = 0; i < 16; i++)
    {

     //判断字节数是否在0xB1和0xD7之间,如果在这之间且在奇数位,odd++,要不even++
     if(temp[i] > (byte)0xB1 && temp[i] < (byte)0xD7)
     {
      if(i%2 == 1) odd++;
      else   even++;
     }
    }
    System.out.println("The odd is " + odd + " and the even is " + even);

    //如果odd大于even,从当前页的前三个字节开始读bytesofeachpage + 3个字节,要不就只读当前页bytesofeachpage个字节
    if(odd > even) 
    {
     txtFile.seek(page * bytesofeachpage - 3);
     buffer = new byte[bytesofeachpage + 3];
     txtFile.read(buffer, 0, bytesofeachpage + 3);
    }
    else
    {
     buffer = new byte[bytesofeachpage];
     txtFile.seek(page * bytesofeachpage);
     txtFile.read(buffer, 0, bytesofeachpage);
    }
   }
   else
   {
    buffer = new byte[bytesofeachpage];
    txtFile.seek(page * bytesofeachpage);
    txtFile.read(buffer, 0, bytesofeachpage);
   }
   txtContent.setText(new String(buffer, encoding));

这个做法很好的解决了问题,当然同时又想出了其他的办法(有时候,人就是这样,遇到问题时,怎么都想不出解决办法,好不容易解决了之后,就同时冒出了其他更好的解决办法,悲催呀)。还可以数字节一直数到遇到第一个ASCII,偶数不变,奇数往前多读一个字节。当然,这种办法如果整页都是GB2312就很悲催了。

 

在做这个期间,看了其他的阅读器,如百度文库、iReader、开卷有益之类的是怎么做到又快又能分页阅读还能跳到百分之几的呢?我还有很长的路要走呀,但是目前,还是先去学好Linux及系统编程先!