为啥我不能在方法之外调用变量? [复制]

Posted

技术标签:

【中文标题】为啥我不能在方法之外调用变量? [复制]【英文标题】:why i cant call the variable outside of method? [duplicate]为什么我不能在方法之外调用变量? [复制] 【发布时间】:2019-12-02 07:57:02 【问题描述】:

在这个解决方案的帖子中,我可以在 void 中调用变量。 当我试图在 void 之外调用它时,数据是空的。

链接:I cant get the values from Firebase and put them in to TextView in fragment

我已经将变量定义为 public。

编辑:

public class FormSendActivity extends AppCompatActivity 

// form edit text
EditText email ;
EditText perihal;
EditText deskripsi;

TextView tes;

// variabel untuk menyimpan data dari edit text menjadi string
public String emails;
public String perihals;
public String deskripsis;

//variabel untuk menampung datauser sesuai login
public String getnama;
public String getusername;

FirebaseAuth firebaseAuth;
public String uid ;

Button kirim;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_form_send);


    email = (EditText) findViewById(R.id.editText);
    perihal = (EditText) findViewById(R.id.editText2);
    deskripsi = (EditText) findViewById(R.id.editText4);
    kirim = (Button) findViewById(R.id.button);
    tes = (TextView) findViewById(R.id.textView3);

    firebaseAuth = firebaseAuth.getInstance();
    uid = firebaseAuth.getCurrentUser().getUid();

    dapatdatauser(uid);  // here i call the method of bottom, and put in to a variabel
    tes.setText(getusername); //  here i put the variabel to textview to test

    kirim.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 

            emails = email.getText().toString();
            perihals = perihal.getText().toString();
            deskripsis = deskripsi.getText().toString();

            Sendmail sendmail = new Sendmail(emails,perihals,deskripsis);
            FirebaseDatabase.getInstance().getReference("Sendmail")
                    .child(getusername).child("Outbox").push()
                    .setValue(sendmail).addOnCompleteListener(new OnCompleteListener<Void>() 
                @Override
                public void onComplete(@NonNull Task<Void> task) 
                    if (task.isSuccessful())
                        Toast.makeText(FormSendActivity.this,"Data sudah terkirim !!", Toast.LENGTH_SHORT).show();
                        Intent i = new Intent(FormSendActivity.this, MainActivity.class);
                        finish();
                    else 
                        Toast.makeText(FormSendActivity.this,"Data gagal di kirim !!", Toast.LENGTH_SHORT).show();
                    
                
            );
        
    );




public void dapatdatauser(String iduser)
    // Mendapatkan DataUsers Berdasarkan uid sesuai login
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
    DatabaseReference query = reference.child("DataUsers").child(iduser);
    ValueEventListener valueEventListener = new ValueEventListener() 
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) 
            // Memasukkan data kedalam variabel username
            getusername = dataSnapshot.child("username").getValue(String.class);

        

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) 

        
    ;
    query.addListenerForSingleValueEvent(valueEventListener);
 

这是我的完整代码。 我首先调用方法 dapatdatauser (方法内部设置为变量'getusername'的值) 然后我将变量设置为 textview 来测试它。 但输出为空。

我找到了将所有代码放入方法 onCreate 的解决方案。然后在里面做剩下的事情

public void onDataChange(@NonNull DataSnapshot dataSnapshot) 
        // Memasukkan data kedalam variabel username
        getusername = dataSnapshot.child("username").getValue(String.class);

    

但我只想知道,为什么我的代码首先不起作用? 谢谢

【问题讨论】:

【参考方案1】:

但我只想知道,为什么我的代码在第一个不起作用?

您无法获取getusername 值,因为它是异步操作。数据尚未从数据库加载完毕,因此无法访问。

【讨论】:

即使我将变量设置为公共?它给我空..所以我应该把所有的代码都放在里面? 是的。这是异步的行为。【参考方案2】:

根据firestore 文档 https://firebase.google.com/docs/functions/terminate-functions Cloud Firestoreasynchronous 所以基本上在您的代码中,您在查询将结果设置为变量之前填充数据,您必须在 multi thread 中运行它以避免此问题或设计代码以在之后填充数据操作结束。

我建议你看看这篇文章,它更适合你的情况。

Async with Firestore

【讨论】:

【参考方案3】:

OnCreate 将在创建此类的对象时调用,因此它是一次性操作。 所以这次你的变量只有在onCreate内部初始化时才会被设置。

OnDataChange 是侦听器,在数据更改之前,您不会调用此方法并设置变量。 要么你需要添加

tes.setText(getusername);onDataChange 内,或

getusername = dataSnapshot.child("username").getValue(String.class);

onCreatetes.setText(getusername); 之前

【讨论】:

以上是关于为啥我不能在方法之外调用变量? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能在 main 方法中调用私有变量?

为啥我能够从在同一对象的另一个实例上调用的方法访问一个实例的私有实例变量? [复制]

为啥我不能“直接”从 HTML 调用 Servlet? [复制]

super this 为啥不能同时存在

调用函数时为啥形参的值不能传给实参

为啥可以从对象范围之外调用私有方法?