我正在学习如何使用parse创建聊天客户端的教程。链接:https://github.com/codepath/android_guides/wiki/Building-Simple-Chat-Client-with-Parse当我在我的应用程序中按发送时,它说“parseapp”已停止。我是一名新程序员,不确定为什么它不起作用。我的代码中没有错误。虽然它必须与按下按钮时有关,或者有一些未使用的变量。请帮忙!提前谢谢。
以下是Actvity的主要代码,我认为该代码最有可能出现问题:
public class ChatActivity extends AppCompatActivity {
static final String TAG = ChatActivity.class.getSimpleName();
static final int MAX_CHAT_MESSAGES_TO_SHOW = 500;
static final String USER_ID_KEY = "userId";
static final String BODY_KEY = "body";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId("indexApp")
.clientKey(null)
.server("http://45.55.25.242:8000/parse/") // The trailing slash is important.
.build()
);
// User login
if (ParseUser.getCurrentUser() != null) { // start with existing user
startWithCurrentUser();
} else { // If not logged in, login as a new anonymous user
login();
}
}
// Get the userId from the cached currentUser object
void startWithCurrentUser() {
// TODO:
setupMessagePosting();
{
// Find the text field and button
etMessage = (EditText) findViewById(R.id.etMessage);
btSend = (Button) findViewById(R.id.btSend);
lvChat = (ListView) findViewById(R.id.lvChat);
mMessages = new ArrayList<>();
// Automatically scroll to the bottom when a data set change notification is received and only if the last item is already visible on screen. Don't scroll to the bottom otherwise.
lvChat.setTranscriptMode(1);
mFirstLoad = true;
final String userId = ParseUser.getCurrentUser().getObjectId();
mAdapter = new ChatListAdapter(ChatActivity.this, userId, mMessages);
lvChat.setAdapter(mAdapter);
// When send button is clicked, create message object on Parse
btSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String data = etMessage.getText().toString();
ParseObject message = ParseObject.create("Message");
message.put(Message.USER_ID_KEY, userId);
message.put(Message.BODY_KEY, data);
message.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
Toast.makeText(ChatActivity.this, "Successfully created message on Parse",
Toast.LENGTH_SHORT).show();
refreshMessages();
}
});
etMessage.setText(null);
}
});
}
}
// Query messages from Parse so we can load them into the chat adapter
void refreshMessages() {
// Construct query to execute
ParseQuery<Message> query = ParseQuery.getQuery(Message.class);
// Configure limit and sort order
query.setLimit(MAX_CHAT_MESSAGES_TO_SHOW);
query.orderByAscending("createdAt");
// Execute query to fetch all messages from Parse asynchronously
// This is equivalent to a SELECT query with SQL
query.findInBackground(new FindCallback<Message>() {
public void done(List<Message> messages, ParseException e) {
if (e == null) {
mMessages.clear();
mMessages.addAll(messages);
mAdapter.notifyDataSetChanged(); // update adapter
// Scroll to the bottom of the list on initial load
if (mFirstLoad) {
lvChat.setSelection(mAdapter.getCount() - 1);
mFirstLoad = false;
}
} else {
Log.e("message", "Error Loading Messages" + e);
}
}
});
}
// Create an anonymous user using ParseAnonymousUtils and set sUserId
void login() {
ParseAnonymousUtils.logIn(new LogInCallback() {
@Override
public void done(ParseUser user, ParseException e) {
if (e != null) {
Log.e(TAG, "Anonymous login failed: ", e);
} else {
startWithCurrentUser();
}
}
});
}
EditText etMessage;
Button btSend;
ListView lvChat;
ArrayList<Message> mMessages;
ChatListAdapter mAdapter;
// Keep track of initial load to scroll to the bottom of the ListView
boolean mFirstLoad;
void setupMessagePosting() {
// Find the text field and button
etMessage = (EditText) findViewById(R.id.etMessage);
btSend = (Button) findViewById(R.id.btSend);
// When send button is clicked, create message object on Parse
btSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String data = etMessage.getText().toString();
ParseObject message = ParseObject.create("Message");
message.put(Message.USER_ID_KEY, ParseUser.getCurrentUser().getObjectId());
message.put(Message.BODY_KEY, data);
message.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
Toast.makeText(ChatActivity.this, "Successfully created message on Parse",
Toast.LENGTH_SHORT).show();
}
});
etMessage.setText(null);
}
});
}
// Create a handler which can run code periodically
static final int POLL_INTERVAL = 1000; // milliseconds
Handler mHandler = new Handler(); // android.os.Handler
Runnable mRefreshMessagesRunnable = new Runnable() {
@Override
public void run() {
refreshMessages();
mHandler.postDelayed(this, POLL_INTERVAL);
setContentView(R.layout.activity_chat);
if (ParseUser.getCurrentUser() != null) {
startWithCurrentUser();
} else {
login();
}
mHandler.postDelayed(mRefreshMessagesRunnable, POLL_INTERVAL);
}
};
}
这是布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.patri.parseapp.ChatActivity">
<ListView
android:id="@+id/lvChat"
android:transcriptMode="alwaysScroll"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_above="@+id/rlSend"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<RelativeLayout
android:id="@+id/rlSend"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:paddingTop="5dp"
android:paddingBottom="10dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:layout_height="wrap_content" >
<EditText
android:id="@+id/etMessage"
android:layout_toLeftOf="@+id/btSend"
android:layout_alignBottom="@+id/btSend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top"
android:hint="hint"
android:inputType="textShortMessage"
android:imeOptions="actionSend"
/>
<Button
android:id="@+id/btSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|right"
android:paddingRight="10dp"
android:layout_alignParentRight="true"
android:text="send"
android:textSize="18sp" >
</Button>
</RelativeLayout>
</RelativeLayout>
这是我的适配器:
public class ChatListAdapter extends ArrayAdapter<Message> {
private String mUserId;
public ChatListAdapter(Context context, String userId, List<Message> messages) {
super(context, 0, messages);
this.mUserId = userId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).
inflate(R.layout.chat_item, parent, false);
final ViewHolder holder = new ViewHolder();
holder.imageOther = (ImageView)convertView.findViewById(R.id.ivProfileOther);
holder.imageMe = (ImageView)convertView.findViewById(R.id.ivProfileMe);
holder.body = (TextView)convertView.findViewById(R.id.tvBody);
convertView.setTag(holder);
}
final Message message = getItem(position);
final ViewHolder holder = (ViewHolder)convertView.getTag();
final boolean isMe = message.getUserId() != null && message.getUserId().equals(mUserId);
// Show-hide image based on the logged-in user.
// Display the profile image to the right for our user, left for other users.
if (isMe) {
holder.imageMe.setVisibility(View.VISIBLE);
holder.imageOther.setVisibility(View.GONE);
holder.body.setGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
} else {
holder.imageOther.setVisibility(View.VISIBLE);
holder.imageMe.setVisibility(View.GONE);
holder.body.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
}
final ImageView profileView = isMe ? holder.imageMe : holder.imageOther;
Picasso.with(getContext()).load(getProfileUrl(message.getUserId())).into(profileView);
holder.body.setText(message.getBody());
return convertView;
}
// Create a gravatar image based on the hash value obtained from userId
private static String getProfileUrl(final String userId) {
String hex = "";
try {
final MessageDigest digest = MessageDigest.getInstance("MD5");
final byte[] hash = digest.digest(userId.getBytes());
final BigInteger bigInt = new BigInteger(hash);
hex = bigInt.abs().toString(16);
} catch (Exception e) {
e.printStackTrace();
}
return "http://www.gravatar.com/avatar/" + hex + "?d=identicon";
}
final class ViewHolder {
public ImageView imageOther;
public ImageView imageMe;
public TextView body;
}
}
这是一个与消息如何工作相关的活动类:
@ParseClassName("Message")
public class Message extends ParseObject {
public static final String USER_ID_KEY = "userId";
public static final String BODY_KEY = "body";
public String getUserId() {
return getString(USER_ID_KEY);
}
public String getBody() {
return getString(BODY_KEY);
}
public void setUserId(String userId) {
put(USER_ID_KEY, userId);
}
public void setBody(String body) {
put(BODY_KEY, body);
}
}
我不认为任何其他代码会被使用,但如果代码似乎被遗漏了,我将进行编辑。
我的错误说
com.parse.ParseObject无法强制转换为com.example.patri.parseapp.Message
我看了这个错误,没有任何解决方案可以在stackOverflow上运行。
编辑:Logcat
07-28 20:10:08.788 9922-9922 / com.example.patri.parseapp E / AndroidRuntime:FATAL EXCEPTION:main 处理:com.example.patri.parseapp,PID:9922
java.lang.ClassCastException: com.parse.ParseObject cannot be cast to com.example.patri.parseapp.Message
at com.example.patri.parseapp.ChatListAdapter.getView(ChatListAdapter.java:40)
at android.widget.AbsListView.obtainView(AbsListView.java:2347)
at android.widget.ListView.measureHeightOfChildren(ListView.java:1270)
at android.widget.ListView.onMeasure(ListView.java:1182)
at android.view.View.measure(View.java:17565)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:727)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:463)
at android.view.View.measure(View.java:17565)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5537)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135)
at android.view.View.measure(View.java:17565)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5537)
at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:391)
at android.view.View.measure(View.java:17565)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5537)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at android.view.View.measure(View.java:17565)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5537)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
at android.view.View.measure(View.java:17565)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5537)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2615)
at android.view.View.measure(View.java:17565)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2045)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1196)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1409)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1084)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5990)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
07-28 20:10:10.729 9922-9922/com.example.patri.parseapp I/Process: Sending signal. PID: 9922 SIG: 9
答案 0 :(得分:1)
总的来说,我不明白你为什么会收到这个错误。但是,正如注释中所解释的那样,所有Message对象都是ParseObject,但并不是所有的ParseObject都可以转换为Message,因此错误,但你没有强制转换,你的错误似乎在rule number, permit/deny, protocol, source IP, source port, des ip, des port.
1, permit, tcp, any, any, 10.1.2.230, 9091
2, permit, tcp, any, any, 10.1.2.241, pptp
,其中可能会发生隐式演员,但不应该因为你已经扩展final Message message = getItem(position)
以下是您可以尝试的一些事项。
使用对象类型
声明arraylistArrayAdapter<Message>
确保此处的此字符串是Parse表的名称
mMessages = new ArrayList<Message>();
实现适配器的@ParseClassName("Message")
方法。
getItem