为什么是空的,当我需要他们设定的听众得到通知? (在Android应用程序) [英] Why is the set of listeners empty when I need them to be notified? (in an Android app)

查看:132
本文介绍了为什么是空的,当我需要他们设定的听众得到通知? (在Android应用程序)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Andr​​oid应用我有三个班,一个是在MainActivity另一个叫CustomerTransaction,这仅仅是一个Java类。还有一个名为DataActivity另一个活动而启动时被点击在MainActivity屏幕按钮输入数据。活动DataActivity允许用户在一个EditText输入一个号码,然后点击发送按钮来触发CustomerTransaction的方法。我将在下面添加完整的code。但是,首先让我解释一下我的问题。在CustomerTransaction我有两个变量提供值的方法:总金额和TRANSACTIONTYPE(均为INT)。需要在MainActivity此值主屏幕上显示,他们的空闲。在MainActivity实现所谓含有显示两个值(在TextViews)的函数的标头CustomListeners的接口。值由通知监听器时的值可从CustomerTransaction传送到该方法中MainActivity。问题是,当我有价值观,侦听器集是空的。我想知道为什么发生这种情况,然后纠正code。

这里的code:

 包com.example.customlistenertest;进口android.app.Activity;
进口android.content.Intent;
进口android.os.Bundle;
进口android.view.View;
进口android.view.View.OnClickListener;
进口android.widget.Button;
进口android.widget.TextView;公共类MainActivity扩展活动实现CustomListeners {
TextView的tv_amount;
TextView的tv_transactionType;
按钮btn_enterData;
CustomerTransaction控制=新CustomerTransaction();@覆盖
公共无效的onCreate(捆绑savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.activity_main);
    control.registerListener(本);    tv_amount =(的TextView)findViewById(R.id.textView_amount);
    tv_transactionType =(的TextView)findViewById(R.id.textView_transactionType);
    btn_enterData =(按钮)findViewById(R.id.button_enterData);    addListenerOnButtonEnterData();
}公共无效addListenerOnButtonEnterData(){
    btn_enterData.setOnClickListener(新OnClickListener(){@覆盖
公共无效的onClick(查看为arg0){
意向意图=
新意图(MainActivity.this,com.example.customlistenertest.DataActivity.class);
startActivity(意向);
        }
    });}公共无效updateTotal(最终诠释TRANSACTIONTYPE,最终诠释总金额){
   runOnUiThread(新的Runnable(){
   公共无效的run(){
    tv_amount.setText(Integer.toString(总金额));
    tv_transactionType.setText(Integer.toString(TRANSACTIONTYPE));
   }});
}@覆盖
公共无效调用onStart(){
    super.onStart();
}
@覆盖
 公共无效onResume(){
    super.onResume();
    control.registerListener(本);
 }
 @覆盖
 保护无效的onPause(){
     super.onPause();
 }@覆盖
 保护无效的onDestroy(){
     super.onDestroy();
     control.unregisterListener(本);
 }} //结束MainActivity

以下是code为DataActivity类:

 包com.example.customlistenertest;进口android.app.Activity;
进口android.os.Bundle;
进口android.view.View;
进口android.widget.Button;
进口android.widget.EditText;
进口android.widget.TextView;公共类DataActivity延伸活动{TextView的tv_enterNumber;
的EditText et_number;
按钮btn_send;
CustomerTransaction交易;@覆盖
公共无效的onCreate(捆绑savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.enter_data);    btn_send =(按钮)findViewById(R.id.button_send);
    et_number =(EditText上)findViewById(R.id.editText_number);
}公共无效发送(查看视图){
    交易=新CustomerTransaction();
    transComplete();
}私人无效transComplete(){
    新的Thread(TransComplete){
        公共无效的run(){
            。字符串s_number = et_number.getText()的toString();
            int值=的Integer.parseInt(s_number);
            transaction.setState(5值);
            完();
        }
    }。开始();
}
} //结束DataActivity

以下是code为CustomerTransaction类:

 包com.example.customlistenertest;进口java.util.HashSet中;
进口java.util.Set中;公共类CustomerTransaction {
公共静态最终诠释DATA_ENTERED = 1;
公共静态最终诠释TRANSACTION_COMPLETE = 5;
私人诠释状态;
私人诠释总金额;
私人诠释TRANSACTIONTYPE;
公开组< CustomListeners>听众=新的HashSet< CustomListeners>();
公共同步无效registerListener(CustomListeners监听){
    listeners.add(监听);
}公共同步无效unregisterListener(CustomListeners监听){
       listeners.remove(监听);
}公共同步无效notifyListeners(){
   对于(CustomListeners监听器:监听器){
 如果(总金额!= 0)
    listener.updateTotal(TRANSACTIONTYPE,总金额);
其他
    listener.updateTotal(TRANSACTIONTYPE,0);
   }
}公共无效performOperation(){  新的Thread(MyThread的){
   公共无效的run(){
    notifyListeners();
 }
 }。开始();
}
公共无效的setState(最终诠释的状态,最终int值){
   this.state =状态;
   this.totalAmount =价值;
   this.transactionType = 999;
   如果(状态== DATA_ENTERED){   }
   如果(状态== TRANSACTION_COMPLETE){
        performOperation();
   }
 }} //结束CustomerTransactionjava

我将添加两个布局的文件。首先是activity_main.xml中:

 <?XML版本=1.0编码=UTF-8&GT?;
< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:方向=垂直><的TextView
    机器人:ID =@ + ID / textView_amount
    机器人:layout_width =WRAP_CONTENT
    机器人:layout_height =WRAP_CONTENT
    机器人:文字=TextView的/><的TextView
    机器人:ID =@ + ID / textView_transactionType
    机器人:layout_width =WRAP_CONTENT
    机器人:layout_height =WRAP_CONTENT
    机器人:文字=TextView的/><按钮
    机器人:ID =@ + ID / button_enterData
    机器人:layout_width =WRAP_CONTENT
    机器人:layout_height =WRAP_CONTENT
    机器人:文字=输入数据/>< / LinearLayout中>

下一个是文件enter_data.xml:

 <?XML版本=1.0编码=UTF-8&GT?;
< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:方向=垂直><的TextView
    机器人:ID =@ + ID / textView_enterNumber
    机器人:layout_width =WRAP_CONTENT
    机器人:layout_height =WRAP_CONTENT
    机器人:文字=输入一个数字:/><的EditText
    机器人:ID =@ + ID / editText_number
    机器人:layout_width =match_parent
    机器人:layout_height =WRAP_CONTENT
    机器人:EMS =10
    安卓的inputType =号>
    < requestFocus的/>
 < /&的EditText GT; <按钮
    机器人:ID =@ + ID / button_send
    机器人:layout_width =WRAP_CONTENT
    机器人:layout_height =WRAP_CONTENT
    安卓的onClick =发送
    机器人:文字=发送/> < / LinearLayout中>

最后,这里的清单文件。

 <清单的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
包=com.example.customlistenertest
安卓版code =1
机器人:=的versionName1.0><用途-SDK
    安卓的minSdkVersion =8
    机器人:targetSdkVersion =19/><应用
   机器人:主题=@风格/ AppTheme
   机器人:allowBackup =真
   机器人:图标=@绘制/ ic_launcher
   机器人:标签=@字符串/ APP_NAME>
    <活动机器人:标签=@字符串/ APP_NAME机器人:名字=MainActivity>
        &所述;意图滤光器>
            <作用机器人:名字=android.intent.action.MAIN/>
            <类机器人:名字=android.intent.category.LAUNCHER/>
        &所述; /意图滤光器>
    < /活性GT;
    <活动机器人:名字=com.example.customlistenertest.DataActivity>
    < /活性GT;
< /用途>
< /清单>


解决方案

在MainActivity使用的CustomerTransaction交易是不是在DataActivity定义的的CustomerTransaction交易的同一个实例。这解释了为什么DataActivity一个是空的,因为你是只从在MainActivity一个订阅。对这个问题有两种可能的解决方案:


  1. 请在控制一个单身,这样你一定会是有它的只有一个实例在同一时间。

  2. 请了听众变量和注册/注销/ notitifylisteners'方法是静态的。

我preFER选项1,但你可以选择你认为这是最好的。

祝你好运!

In my Android app I have three classes, one is the MainActivity another one is called CustomerTransaction, which is just a Java class. There is also another activity called DataActivity which starts when the button Enter Data on the MainActivity screen is clicked. The activity DataActivity allows the user to enter a number in an EditText and then click the Send button to trigger a method in CustomerTransaction. I shall add the complete code below. But first let me explain my problem. In CustomerTransaction I have a method that provides values for two variables: totalAmount and transactionType (both are int). This values are needed in the MainActivity to be displayed on the main screen, when they are available. The MainActivity implements an interface called CustomListeners containing the header of the function that displays the two values (in TextViews). The values are communicated from CustomerTransaction to the method in MainActivity by notifying the listener when the values are available. The problem is that when I have the values, the set of listeners is empty. I would like to understand why this happens and then to correct the code.

Here's the code:

package com.example.customlistenertest;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements CustomListeners {
TextView tv_amount;
TextView tv_transactionType;
Button btn_enterData;
CustomerTransaction control= new CustomerTransaction();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    control.registerListener(this);

    tv_amount = (TextView) findViewById(R.id.textView_amount);
    tv_transactionType = (TextView) findViewById(R.id.textView_transactionType);
    btn_enterData = (Button) findViewById(R.id.button_enterData);

    addListenerOnButtonEnterData();
}

public void addListenerOnButtonEnterData() {
    btn_enterData.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent intent = 
new Intent(MainActivity.this,com.example.customlistenertest.DataActivity.class);       
startActivity(intent); 
        }
    });

}

public void updateTotal(final int transactionType, final int totalAmount) {
   runOnUiThread(new Runnable() {
   public void run() {
    tv_amount.setText(Integer.toString(totalAmount));
    tv_transactionType.setText(Integer.toString(transactionType));
   }});
}

@Override    
public void onStart() {
    super.onStart();
}
@Override
 public void onResume(){
    super.onResume();
    control.registerListener(this);
 }
 @Override
 protected void onPause() {
     super.onPause();
 }

@Override
 protected void onDestroy() {
     super.onDestroy();
     control.unregisterListener(this);
 }

} // End MainActivity

Following is the code for the DataActivity class:

package com.example.customlistenertest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class DataActivity extends Activity {

TextView tv_enterNumber;
EditText et_number;
Button btn_send;
CustomerTransaction transaction;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.enter_data);

    btn_send = (Button) findViewById(R.id.button_send);
    et_number = (EditText) findViewById(R.id.editText_number);
}

public void send(View view) {
    transaction = new CustomerTransaction();
    transComplete();
}

private void transComplete() {
    new Thread("TransComplete") {
        public void run() {
            String s_number = et_number.getText().toString();
            int value = Integer.parseInt(s_number);
            transaction.setState(5, value);
            finish();
        }
    }.start();
}
} // end DataActivity

Following is the code for the CustomerTransaction class:

package com.example.customlistenertest;

import java.util.HashSet;
import java.util.Set;

public class CustomerTransaction {
public static final int DATA_ENTERED = 1;
public static final int TRANSACTION_COMPLETE = 5;
private int state;
private int totalAmount;
private int transactionType;
public Set<CustomListeners> listeners = new HashSet<CustomListeners>();


public synchronized void registerListener(CustomListeners listener) {
    listeners.add(listener);
}

public synchronized void unregisterListener(CustomListeners listener) {
       listeners.remove(listener);
}

public synchronized void notifyListeners() {
   for(CustomListeners listener : listeners) {
 if (totalAmount != 0)
    listener.updateTotal(transactionType,totalAmount);
else
    listener.updateTotal(transactionType,0);
   }
}

public void performOperation() {

  new Thread("MyThread") {
   public void run() { 
    notifyListeners();
 }
 }.start();
}    
public void setState(final int state, final int value) {
   this.state = state;
   this.totalAmount = value;
   this.transactionType = 999;
   if (state == DATA_ENTERED) {

   }
   if (state == TRANSACTION_COMPLETE) {
        performOperation();
   }
 }

} // end CustomerTransactionjava

I shall add the two layout files as well. The first is activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

<TextView
    android:id="@+id/textView_amount"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView" />

<TextView
    android:id="@+id/textView_transactionType"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView" />

<Button
    android:id="@+id/button_enterData"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Enter Data" />

</LinearLayout>

The next one is the file enter_data.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

<TextView
    android:id="@+id/textView_enterNumber"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Enter a number:" />

<EditText
    android:id="@+id/editText_number"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ems="10"
    android:inputType="number" >
    <requestFocus />
 </EditText>

 <Button
    android:id="@+id/button_send"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="send"
    android:text="Send" />

 </LinearLayout>

Finally, here's the Manifest file.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.customlistenertest"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="19" />

<application 
   android:theme="@style/AppTheme" 
   android:allowBackup="true"
   android:icon="@drawable/ic_launcher"
   android:label="@string/app_name">
    <activity android:label="@string/app_name" android:name="MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name="com.example.customlistenertest.DataActivity" >    
    </activity>
</application>
</manifest>

解决方案

The "CustomerTransaction transaction" used in the MainActivity is not the same instance of the "CustomerTransaction transaction" of the one defined in the DataActivity. That explains why the DataActivity one is empty, because you did subscribe only with the one from the MainActivity. Two possible solutions for the problem:

  1. Make the 'control' a singleton, so that you will be sure that there is only one instance of it at a time.
  2. Make the 'listeners' variables and the 'register/unregister/notitifylisteners' methods static.

I prefer the option 1, but you can choose what you think it's best.

Good luck!

这篇关于为什么是空的,当我需要他们设定的听众得到通知? (在Android应用程序)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆