我正在编写一个货币转换器应用程序并使用 Volley 请求向 API 发送请求以检索转换率。
我现在有两个微调器(来自货币和目标货币)。我有三个功能,一个用于将项目添加到微调器,一个用于在按下按钮时添加监听器,一个用于发送 volley 请求以检索 JSON 信息。
我相信我正在以正确的顺序调用函数,但是无论出于何种原因,toSpinnerText
和 fromSpinnerText
的值似乎都没有设置为纺纱厂。在我看来,它们应该在发送对 url 的请求之前设置,因为我在 jsonSendRequest()
之前调用了 addItemsOnToSpinner()
。但是当我使用日志调用进行调试时,toSpinnerText
和 fromSpinnerText
的值在构造 url 字符串时仍然是空字符串。
这是我目前所拥有的。谢谢。
public class MainActivity extends AppCompatActivity {
RequestQueue rq;
Double conversionDouble;
Spinner toSpinner, fromSpinner;
String toSpinnerText = "";
String fromSpinnerText = "";
private Button convertBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addItemsOnToSpinner();
addListenerOnButton();
jsonSendRequest();
Button convertBtn = (Button) findViewById(R.id.convertBtn);
final EditText fromAmountEditText = findViewById(R.id.fromAmountEditText);
convertBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView toAmountTextView = findViewById(R.id.toAmountTextView);
DecimalFormat percentageFormat = new DecimalFormat("0.00");
Double fromAmount = Double.parseDouble(fromAmountEditText.getText().toString());
String result = "$" + percentageFormat.format(conversionDouble*fromAmount);
toAmountTextView.setText(result);
}
});
rq = Volley.newRequestQueue(this);
}
public void jsonSendRequest() {
RequestQueue queue = Volley.newRequestQueue(this);
// String url = "http://free.currencyconverterapi.com/api/v3/convert?q=CAD_USD&compact=ultra";
String url = "http://free.currencyconverterapi.com/api/v3/convert?q=" + fromSpinnerText + "_" + toSpinnerText + "&compact=ultra";
// Request a string response
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
JSONObject jsonobject = null;
try {
jsonobject = new JSONObject(response);
} catch (JSONException e) {
e.printStackTrace();
}
if (jsonobject.has(fromSpinnerText + "_" + toSpinnerText)) {
try {
conversionDouble = jsonobject.getDouble(fromSpinnerText + "_" + toSpinnerText);
// conversionDouble = jsonobject.getDouble(fromSpinnerText + "_" + toSpinnerText);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
public void addItemsOnToSpinner(){
Spinner toSpinner = (Spinner) findViewById(R.id.toSpinner);
Spinner fromSpinner = (Spinner) findViewById(R.id.fromSpinner);
List<String> currency = new ArrayList<String>();
currency.add("USD");
currency.add("CAD");
currency.add("CNY");
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(
this, android.R.layout.simple_spinner_item, currency
);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
toSpinner.setAdapter(dataAdapter);
fromSpinner.setAdapter(dataAdapter);
fromSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String fromSpinnerText = (String) parent.getItemAtPosition(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
toSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String toSpinnerText = (String) parent.getItemAtPosition(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
public void addListenerOnButton() {
Spinner fromSpinner = (Spinner) findViewById(R.id.fromSpinner);
Spinner toSpinner = (Spinner) findViewById(R.id.toSpinner);
Button convertBtn = (Button) findViewById(R.id.convertBtn);
}
}
最佳答案
首先你在评论中提到你不需要 addListenerOnButton()
我已尝试尽可能多地在代码中添加注释,以便您可以关注我所做的更改。
public class MainActivity extends AppCompatActivity {
//Always create a TAG it is very useful when logging to the logcat!
private static final String TAG = MainActivity.class.getSimpleName();
//Not used! Not needed!
//RequestQueue rq = null;
// I like to have all my class variables defined at the beginning--even if it is just null!
//Class variable to hold the object throughout the class!
Spinner toSpinner = null;
Spinner fromSpinner = null;
Button convertBtn = null;
//Class variable to hold the object throughout the class!
EditText fromAmountEditText = null;
TextView toAmountTextView = null;
String toSpinnerText = "";
String fromSpinnerText = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createSpinnerAddData();
// convertBtn is a class variable defined above--do not create a local variable here
convertBtn = (Button) findViewById(R.id.convertBtn);
// fromAmountEditText is a class variable defined above--do not create a local variable here
fromAmountEditText = findViewById(R.id.fromAmountEditText);
// toAmountTextView is a class variable defined above--do not create a local variable here
toAmountTextView = findViewById(R.id.toAmountTextView);
convertBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Perform your request here--after the currencies have been selected!
jsonSendRequest();
}
});
//Dont use it--Dont need it!
//rq = Volley.newRequestQueue(this);
}
// this does not need to be public!
private void jsonSendRequest() {
RequestQueue queue = Volley.newRequestQueue(this);
// String url = "http://free.currencyconverterapi.com/api/v3/convert?q=CAD_USD&compact=ultra";
String url = "http://free.currencyconverterapi.com/api/v3/convert?q=" + fromSpinnerText + "_" + toSpinnerText + "&compact=ultra";
// Request a string response
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//onResponse is asynchronous it is called when the data is available, but it executes on the UI thread
JSONObject jsonobject = null;
try {
jsonobject = new JSONObject(response);
} catch (JSONException e) {
e.printStackTrace();
}
if (jsonobject.has(fromSpinnerText + "_" + toSpinnerText)) {
try {
//conversionDouble is only used here so it can be a local variable!
Double conversionDouble = jsonobject.getDouble(fromSpinnerText + "_" + toSpinnerText);
// conversionDouble = jsonobject.getDouble(fromSpinnerText + "_" + toSpinnerText);
//now the data has returned from the async request and is ready to be used..
//...do the conversion, now!
DecimalFormat percentageFormat = new DecimalFormat("0.00");
Double fromAmount = Double.parseDouble(fromAmountEditText.getText().toString());
String result = "$" + percentageFormat.format(conversionDouble*fromAmount);
toAmountTextView.setText(result);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
// this does not need to be public!
private void createSpinnerAddData(){
//The spinners were already defined in the onCreate method--please do not create local variables!!
//Spinner toSpinner = (Spinner) findViewById(R.id.toSpinner);
//Spinner fromSpinner = (Spinner) findViewById(R.id.fromSpinner);
// fromSpinner is a class variable defined above--do not create a local variable here
fromSpinner = (Spinner) findViewById(R.id.fromSpinner);
// toSpinner is a class variable defined above--do not create a local variable here
toSpinner = (Spinner) findViewById(R.id.toSpinner);
List<String> currency = new ArrayList<String>();
currency.add("USD");
currency.add("CAD");
currency.add("CNY");
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, currency);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
toSpinner.setAdapter(dataAdapter);
fromSpinner.setAdapter(dataAdapter);
fromSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
//This has also been defined as a class variable--please do not create local variable!!
//String fromSpinnerText = (String) parent.getItemAtPosition(position);
//...Instead use the class variable
fromSpinnerText = (String) parent.getItemAtPosition(position);
Log.e(TAG, "fromSpinnerText = " + fromSpinnerText);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
toSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
//Same principle as above
toSpinnerText = (String) parent.getItemAtPosition(position);
Log.e(TAG, "toSpinnerText = " + toSpinnerText);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
在上面的评论中也提到:了解public
、protected
和private
方法和变量之间的区别非常重要,因为以及变量的范围......何时使用类变量和局部变量。作为一名程序员,这将对您大有裨益!祝你好运,继续学习!
如果您有任何问题 -- 我会尽力提供帮助。
关于java - Android - 类变量未及时分配 setOnItemSelectedListener 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50669590/