当前位置: 首页 > 知识库问答 >
问题:

简单的聊天客户端应用程序在点击按钮时关闭

笪烨
2023-03-14

我正在学习如何使用parse创建聊天客户端的教程。链接:https://github.com/codepath/android_guides/wiki/Building-Simple-Chat-Client-with-Parse当我在应用程序中按下发送时,它会说“parseapp”已经停止。我是一名新程序员,不确定为什么它不起作用。我的代码中没有错误。尽管这一定与按下按钮的时间有关,或者有一些变量没有被使用。请帮忙!事先谢谢。

这是我认为最有可能出现问题的主要行为代码:

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);
}
}

我不认为任何其他代码会有用,但如果代码似乎被遗漏,我会进行编辑。

我的错误是

通用域名格式。作语法分析无法将ParseObject强制转换为com。实例帕特里。parseapp。消息

我查过这个错误,没有一个解决方案对stackOverflow有效。

编辑:Logcat

07-28 20:10:08.788 9922-9922/com。实例帕特里。parseapp E/AndroidRuntime:致命异常:主进程:com。实例帕特里。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

共有1个答案

段干宏硕
2023-03-14

总的来说,我不明白你为什么会犯这样的错误。但是,正如注释中所解释的,所有消息对象都是ParseObject,但并非所有ParseObject都可以转换为消息,因此会出现错误,但您没有转换,并且您的错误似乎出现在final Message Message=getItem(position),其中可能会发生隐式转换,但不应该发生,因为您扩展了ArrayAdapter

这里有一些你可以尝试的事情。

用对象类型声明arraylist

mMessages = new ArrayList<Message>();

确保这里的字符串是解析表的名称

@ParseClassName("Message")

实现适配器的getItem方法。

public class ChatListAdapter extends ArrayAdapter<Message> {
    private String mUserId;
    private ArrayList<Message> messages;

public ChatListAdapter(Context context, String userId, ArrayList<Message> messages) {
    super(context, 0, messages);
    this.mUserId = userId;
    this.messages = messages;
}  

@Override 
public Message getItem(int position) { 
    return messages.get(position);
} 

 类似资料:
  • 在logcat我看到了这个- 需要关于发生了什么以及如何解决的建议。我使用的是android studio北极狐2020.3.1补丁3。

  • 当用户在我的通知中单击一个按钮时,我正试图打开,而该应用程序仅在后台运行并提供服务。单击按钮时,这些行在类中被触发: 我已经检查过了,这些行被触发了,所以对按钮的点击做出反应没有问题,但是不会打开。 有什么建议吗?为什么这对我不起作用,我怎么能让它起作用? 我被要求提供更多的代码,因此在我的

  • 问题内容: 我一直试图在Eclipse中制作我的第一个android应用程序(一个简单的温度转换器),但是当我单击手机上的按钮时,该应用程序崩溃了。这是完整的Java代码 单击按钮时的LogCat 最后是按钮的xml 我不确定如何解决此问题,因此希望有人可以提供帮助。谢谢。 问题答案: 首先初始化您的按钮,然后将onclicklistener设置为它们 同样设置另一个按钮

  • 我对python有点陌生,这是我第一次使用套接字,我试图制作一个具有客户端和服务器的应用程序,用户可以在客户端中输入,它将被发送到服务器,然后将其发送给所有其他客户端。我已经将其设置为工作状态,但每当我尝试发送第二条消息时,我总是收到一个错误错误:[Errno 10058]发送或接收数据的请求被禁止,因为套接字已经在之前的关闭调用中关闭了该方向。我如何才能做到这一点? 尝试在启动新套接字或发送新消

  • 每次我点击按钮1,我的应用程序就会崩溃。同一活动中的另一个按钮可以正常工作。我已经试过更换按钮和代码了。控制台中没有错误。

  • 这是崩溃错误logcat,每次我时钟在我的寄存器btn应用程序崩溃。 我的模拟器是在Android模拟器设备上的2gb ram。 2019-09-22 16:36:39.307 6454-6454/com。康奈克斯。connexsocial E/AndroidRuntime:致命异常:主进程:com。康奈克斯。connexsocial,PID:6454Android系统。所容纳之物Activity