我正在开发自己的消息应用程序,可以向服务器发送和接收消息。
我正在使用一个名为状态的整数数组,表示消息是传出或传入。
当我在MessageActivity下一行注释时,listview显示了一些消息,但是当我向下滚动时,我的应用程序崩溃了,我得到编排错误。
holder.ivReceiveUser.setImageBitmap(BitmapFactory.decodeFile(userImage));
此外,当我不评论以上行,我得到BitmapFactory错误。(我确定imagePath是true,因为我在其他活动中使用了它)
MessageActivity
private void initListview()
{
lv = (ListView) findViewById(R.id.lv_messages);
MessagesList = dbh.getAllMessagesOfSpecificUser(TargetUserID);
final String img = TargetModel.getImagePath();
String username = TargetModel.getName();
String[] Content = new String[MessagesList.size()];
String[] MessageID = new String[MessagesList.size()];
String[] SendDate = new String[MessagesList.size()];
int[] Status = new int[MessagesList.size()];
String[] ReadDate = new String[MessagesList.size()];
for(int i=0; i<MessagesList.size(); i++)
{
Content[i] = MessagesList.get(i).getContent();
MessageID[i] = MessagesList.get(i).getMessageID();
SendDate[i] = MessagesList.get(i).getSendDate();
Status[i] = MessagesList.get(i).getStatus();
ReadDate[i] = MessagesList.get(i).getReadDate();
}
mAdapter = new AdapterMessagesII(MessagesActivity.this, MessageID, Content, SendDate, ReadDate, Status, username, img);
lv.setAdapter(mAdapter);
}
AdapterMessagesII
package MyPackageName.Adapters;
import MyPackageName.R;
import com.pkmmte.circularimageview.CircularImageView;
import android.content.Context;
import android.graphics.Typeface;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
public class AdapterMessagesII extends BaseAdapter {
private LayoutInflater inflater;
private Typeface tf;
private CharSequence time;
private String[] MessageID;
private String[] Content;
private String[] SendDate;
private String[] ReadDate;
private int[] Status;
private String Username;
private String userImage;
public AdapterMessagesII(Context context, String[] MessageID, String[] Content, String[] SendDate, String[] ReadDate, int[] Status, String Username, String userImage)
{
inflater = LayoutInflater.from(context);
this.MessageID = MessageID;
this.Content = Content;
this.SendDate = SendDate;
this.ReadDate = ReadDate;
this.Status = Status;
this.Username = Username;
this.userImage = userImage;
tf = Typeface.createFromAsset(context.getAssets(),"fonts/MJ_DINAR ONE LIGHT.TTF");
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return MessageID.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return MessageID[position];
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder = null;
if (convertView == null)
{
holder = new ViewHolder();
switch (Status[position])
{
case 0: //Send
convertView = inflater.inflate(R.layout.list_messages_row_send, null);
holder.tvSendContent = (TextView) convertView.findViewById(R.id.tv_send_message_content);
holder.tvSendTimestamp = (TextView) convertView.findViewById(R.id.tv_send_message_timestamp);
holder.tvSendReadDate = (TextView) convertView.findViewById(R.id.tv_send_message_read_status);
holder.layoutReadStatus = (LinearLayout) convertView.findViewById(R.id.layout_send_message_read_status);
break;
case 1: //Receive
convertView = inflater.inflate(R.layout.list_messages_row_receive, null);
holder.tvUsername = (TextView) convertView.findViewById(R.id.tv_receive_message_username);
holder.tvReceiveContent = (TextView) convertView.findViewById(R.id.tv_receive_message_content);
holder.tvReceiveTimestamp = (TextView) convertView.findViewById(R.id.tv_receive_message_timestamp);
holder.ivReceiveUser = (CircularImageView) convertView.findViewById(R.id.iv_receive_message);
break;
}
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
switch (Status[position])
{
case 0: //Send
holder.tvSendContent.setText(Content[position]);
time = DateUtils.getRelativeTimeSpanString(Long.parseLong(SendDate[position]),
System.currentTimeMillis(),DateUtils.SECOND_IN_MILLIS);
holder.tvSendTimestamp.setText(time);
switch(ReadDate[position])
{
case "x":
break;
default:
holder.layoutReadStatus.setVisibility(View.VISIBLE);
time = DateUtils.getRelativeTimeSpanString(Long.parseLong(ReadDate[position]),
System.currentTimeMillis(),DateUtils.SECOND_IN_MILLIS);
holder.tvSendReadDate.setText(time);
break;
}
break;
case 1: //Receive
switch(userImage)
{
case "x": holder.ivReceiveUser.setImageResource(R.drawable.avatar_male_dark);
break;
default: holder.ivReceiveUser.setImageBitmap(BitmapFactory.decodeFile(userImage));
break;
}
holder.tvUsername.setText(Username);
holder.tvUsername.setTypeface(tf);
holder.tvReceiveContent.setText(Content[position]);
time = DateUtils.getRelativeTimeSpanString(Long.parseLong(SendDate[position]),
System.currentTimeMillis(),DateUtils.SECOND_IN_MILLIS);
holder.tvReceiveTimestamp.setText(time);
break;
}
return convertView;
}
static class ViewHolder
{
TextView tvUsername;
TextView tvReceiveContent;
TextView tvReceiveTimestamp;
CircularImageView ivReceiveUser;
TextView tvSendContent;
TextView tvSendTimestamp;
TextView tvSendReadDate;
LinearLayout layoutReadStatus;
}
}
list_messages_row_receive
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/ MyPackageName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/BackgrounColor"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/layout_receive_messages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:orientation="horizontal"
android:paddingLeft="5dp" >
<LinearLayout
android:id="@+id/qq"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical" >
<com.pkmmte.circularimageview.CircularImageView
android:id="@+id/iv_receive_message"
android:layout_width="45dp"
android:layout_height="45dp"
app:border="true"
app:border_color="@color/LightGray"
app:border_width="0dp" />
<TextView
android:id="@+id/tv_receive_message_timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/messagesTimestamp"
android:textSize="8sp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:gravity="left"
android:orientation="vertical"
android:paddingTop="5dp" >
<TextView
android:id="@+id/tv_receive_message_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/colorPrimary"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_receive_message_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:background="@drawable/receive_message"
android:gravity="right"
android:lineSpacingMultiplier="1.5"
android:maxWidth="350dp"
android:minWidth="35dp"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/darkGray"
android:textSize="9sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
list_messages_row_send
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_send_messages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:background="@color/BackgrounColor"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:orientation="horizontal"
android:paddingRight="5dp" >
<TextView
android:id="@+id/tv_send_message_timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginRight="5dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/messagesTimestamp"
android:textSize="8sp" />
<TextView
android:id="@+id/tv_send_message_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:background="@drawable/send_message"
android:gravity="right"
android:lineSpacingMultiplier="1.5"
android:maxWidth="350dp"
android:minWidth="35dp"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/white"
android:textSize="9sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout_send_message_read_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_marginTop="2dp"
android:gravity="right|center_vertical"
android:paddingRight="5dp"
android:visibility="gone"
android:orientation="horizontal" >
<ImageView
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_marginRight="2dp"
android:src="@drawable/icon_correct" />
<TextView
android:id="@+id/tv_send_message_read_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/messagesTimestamp"
android:textSize="8sp" />
</LinearLayout>
</LinearLayout>
更新:
Logcat:
08-08 16:45:39.604: I/LOG_ITEM_IMG(2872): /storage/emulated/0/MyAppName/UserImage/010DEC12-A89A-4ACC-B6BE-7FCC677D9526.jpg
08-08 16:45:39.656: D/dalvikvm(2872): GC_FOR_ALLOC freed 1296K, 26% free 43552K/58680K, paused 4ms, total 6ms
08-08 16:45:39.660: I/dalvikvm-heap(2872): Grow heap (frag case) to 55.924MB for 14017548-byte allocation
08-08 16:45:39.664: D/dalvikvm(2872): GC_FOR_ALLOC freed 16K, 3% free 57225K/58680K, paused 7ms, total 7ms
08-08 16:45:39.736: W/Settings(2872): Setting airplane_mode_on has moved from android.provider.Settings.System to android.provider.Settings.Global, returning read-only value.
08-08 16:45:39.788: D/dalvikvm(2872): GC_FOR_ALLOC freed 17191K, 32% free 40169K/58680K, paused 6ms, total 6ms
08-08 16:45:39.800: I/dalvikvm-heap(2872): Grow heap (frag case) to 59.047MB for 20756748-byte allocation
08-08 16:45:39.808: D/dalvikvm(2872): GC_FOR_ALLOC freed 1K, 24% free 60438K/78952K, paused 6ms, total 6ms
08-08 16:45:39.860: D/dalvikvm(2872): GC_FOR_ALLOC freed 1K, 20% free 63864K/78952K, paused 4ms, total 4ms
08-08 16:45:39.860: I/dalvikvm-heap(2872): Grow heap (frag case) to 75.760MB for 14017548-byte allocation
08-08 16:45:39.868: D/dalvikvm(2872): GC_FOR_ALLOC freed <1K, 2% free 77553K/78952K, paused 8ms, total 8ms
08-08 16:45:44.380: E/InputEventReceiver(2872): Exception dispatching input event.
更新2:在我的想法错误必须在list_messages_row_send.xml和list_messages_row_receive.xml布局或在我的适配器中使用它们。
因为当我将状态为0或1的消息传递给适配器时,当我滚动listview时没有错误。
但是当我传递一个状态为1或0(第一个状态的逆)的消息时,错误发生
将此功能添加到适配器:
private Bitmap decodeFile(File f) {
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=70;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
(来源:Bitmap Out Of Memory Issues)
,改变holder.ivReceiveUser.setImageBitmap(BitmapFactory.decodeFile(userImage));
到holderholder.ivReceiveUser.setImageBitmap(decodeFile(new File(userImage));
当你上下滚动时,你创建的图像可能已经被垃圾收集,这意味着ListView试图重新创建这些图像,这就是为什么它崩溃了。
您需要使用LruCache或DiskLruCache缓存您的图像。
请阅读这个Android链接,它会帮助你。
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.htmlpublic View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if (convertView == null)
{
holder = new ViewHolder();
switch (Status[position])
{
case 0: //Send
convertView = inflater.inflate(R.layout.list_messages_row_send, null);
holder.tvSendContent = (TextView) convertView.findViewById(R.id.tv_send_message_content);
holder.tvSendTimestamp = (TextView) convertView.findViewById(R.id.tv_send_message_timestamp);
holder.tvSendReadDate = (TextView) convertView.findViewById(R.id.tv_send_message_read_status);
holder.layoutReadStatus = (LinearLayout) convertView.findViewById(R.id.layout_send_message_read_status);
break;
case 1: //Receive
convertView = inflater.inflate(R.layout.list_messages_row_receive, null);
holder.tvUsername = (TextView) convertView.findViewById(R.id.tv_receive_message_username);
holder.tvReceiveContent = (TextView) convertView.findViewById(R.id.tv_receive_message_content);
holder.tvReceiveTimestamp = (TextView) convertView.findViewById(R.id.tv_receive_message_timestamp);
holder.ivReceiveUser = (CircularImageView) convertView.findViewById(R.id.iv_receive_message);
break;
}
convertView.setTag(持有人);}其他的{holder = (ViewHolder) convertview . getag ();}开关(状态(位置)){case 0://发送holder.tvSendContent.setText(内容(位置));time = DateUtils.getRelativeTimeSpanString(Long.parseLong(SendDate[position])),System.currentTimeMillis (), DateUtils.SECOND_IN_MILLIS);
holder.tvSendTimestamp.setText(时间);if (ReadDate[position] != null){holder.layoutReadStatus.setVisibility (View.VISIBLE);time = DateUtils.getRelativeTimeSpanString(Long.parseLong(ReadDate[position])),System.currentTimeMillis (), DateUtils.SECOND_IN_MILLIS);holder.tvSendReadDate.setText(时间);}//结束if打破;案例1://接收
if (userImage != null){ holder.ivReceiveUser.setImageResource (R.drawable.avatar_male_dark);}其他{holder.ivReceiveUser.setImageBitmap (BitmapFactory.decodeFile (userImage));}holder.tvUsername.setText(用户名);holder.tvUsername.setTypeface (tf);holder.tvReceiveContent.setText(内容(位置));time = DateUtils.getRelativeTimeSpanString(Long.parseLong(SendDate[position])),System.currentTimeMillis (), DateUtils.SECOND_IN_MILLIS);holder.tvReceiveTimestamp.setText(时间);打破;}//结束开关(Status[position])
return convertView;
}
为了简单明了,我建议如下创建2个AdapterClasses;AdapterClass1AdapterClass2类SwitchView扩展AsyncTask{@overrideprotected void doInBackground(Integer…params){int [0];开关(whichView){例0://加载适配器类打破;案例1;//加载适配器类打破;}//结束开关}//结束doinbackgroundonPostExecute(){//取消ProgressDialog}//结束SwitchView