我正在编写一个Android天气应用程序,但我遇到了一个错误,导致我无法在设备或模拟器上运行它。
以下是我的朋友logcat所说的内容:
Process: com.example.tomfinet.stormy, PID: 9378
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tomfinet.stormy/com.example.tomfinet.stormy.MainActivity}: java.lang.RuntimeException: Unable to bind views for com.example.tomfinet.stormy.MainActivity
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2358)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
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:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: java.lang.RuntimeException: Unable to bind views for com.example.tomfinet.stormy.MainActivity
at butterknife.ButterKnife.bind(ButterKnife.java:322)
at butterknife.ButterKnife.bind(ButterKnife.java:237)
at com.example.tomfinet.stormy.MainActivity.onCreate(MainActivity.java:51)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
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:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to android.widget.TextView
at com.example.tomfinet.stormy.MainActivity$$ViewBinder.bind(MainActivity$$ViewBinder.java:14)
at com.example.tomfinet.stormy.MainActivity$$ViewBinder.bind(MainActivity$$ViewBinder.java:8)
at butterknife.ButterKnife.bind(ButterKnife.java:319)
at butterknife.ButterKnife.bind(ButterKnife.java:237)
at com.example.tomfinet.stormy.MainActivity.onCreate(MainActivity.java:51)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
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:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
12-13 21:31:50.763 796-2308/? W/ActivityManager: Force finishing activity 1 com.example.tomfinet.stormy/.MainActivity
12-13 21:31:51.291 796-841/? W/ActivityManager: Activity pause timeout for ActivityRecord{3e556c65 u0 com.example.tomfinet.stormy/.MainActivity t111 f}
以下是MainActivity.java类的内容:
package com.example.tomfinet.stormy;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import butterknife.Bind;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity
{
public static final String TAG = MainActivity.class.getSimpleName();
private CurrentWeather mCurrentWeather;
@Bind(R.id.timeLabel) TextView mTimeLabel;
@Bind(R.id.temperatureLabel) TextView mTemperatureLabel;
@Bind(R.id.humidityValue) TextView mHumidityValue;
@Bind(R.id.precipValue) TextView mPrecipValue;
@Bind(R.id.summaryLabel) TextView mSummaryLabel;
@Bind(R.id.iconImageView) ImageView mIconImageView;
@Bind(R.id.refreshImageView) ImageView mRefreshImageView;
@Bind(R.id.progressBar) ProgressBar mProgressBar;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Replaces declaring private member variable and then finding it via id
ButterKnife.bind(this);
mProgressBar.setVisibility(View.INVISIBLE);
final double latitude = 37.8267;
final double longitude = -122.423;
mRefreshImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getForecast(latitude, longitude);
}
});
}
/**
* Make a simple request and response from to the web
* @param latitude the angular distance of a place north or south of the earth's equator
* @param longitude the angular distance of a place east or west of the Greenwich meridian
*/
private void getForecast(double latitude, double longitude) {
String apiKey = "93a5479657e625c362ccd931b47debe6";
String forecastUrl = "https://api.forecast.io/forecast/" + apiKey +
"/" + latitude + "," + longitude;
if (networkIsAvailable())
{
toggleRefresh();
OkHttpClient client = new OkHttpClient(); //construct
Request request = new Request.Builder()
.url(forecastUrl)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
toggleRefresh();
}
});
alertUserAboutError();
}
@Override
public void onResponse(Response response) throws IOException {
runOnUiThread(new Runnable() {
@Override
public void run() {
toggleRefresh();
}
});
try {
String jsonData = response.body().string(); //stores json data from forecast API
Log.v(TAG, jsonData);
if (response.isSuccessful()) {
mCurrentWeather = getCurrentDetails(jsonData);
runOnUiThread(new Runnable() {
@Override
public void run() {
updateDisplay();
}
});
} else {
alertUserAboutError();
}
} catch (IOException e) {
Log.e(TAG, "Exception caught", e);
} catch (JSONException e) {
Log.e(TAG, "Exception caught", e);
}
}
});
}
}
private void toggleRefresh() {
if (mProgressBar.getVisibility() == View.INVISIBLE)
{
mProgressBar.setVisibility(View.VISIBLE);
mRefreshImageView.setVisibility(View.INVISIBLE);
} else
{
mProgressBar.setVisibility(View.INVISIBLE);
mRefreshImageView.setVisibility(View.VISIBLE);
}
}
private void updateDisplay()
{
mTemperatureLabel.setText(mCurrentWeather.getTemperature() + "");
mTimeLabel.setText("At " + mCurrentWeather.getFormattedTime() + "it will be");
mHumidityValue.setText(mCurrentWeather.getHumidity() + "");
mPrecipValue.setText(mCurrentWeather.getPrecipChance() + "%");
mSummaryLabel.setText(mCurrentWeather.getSummary());
Drawable drawable = getResources().getDrawable(mCurrentWeather.getIconId());
mIconImageView.setImageDrawable(drawable);
}
private CurrentWeather getCurrentDetails(String jsonData) throws JSONException
{
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
Log.i(TAG, "From JSON: " + timezone);
JSONObject currently = forecast.getJSONObject("currently");
CurrentWeather currentWeather = new CurrentWeather();
currentWeather.setHumidity(currently.getDouble("humidity"));
currentWeather.setTime(currently.getLong("time"));
currentWeather.setIcon(currently.getString("icon"));
currentWeather.setPrecipChance(currently.getDouble("precipChance"));
currentWeather.setSummary(currently.getString("summary"));
currentWeather.setTemperature(currently.getDouble("temperature"));
currentWeather.setTimeZone(timezone);
Log.d(TAG, currentWeather.getFormattedTime());
return currentWeather;
}
/**
* @return true for valid network and connectivity
*/
private boolean networkIsAvailable()
{
ConnectivityManager manager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected())
{
return true;
} else
{
Toast.makeText(this, getString(R.string.network_unavailable_message),
Toast.LENGTH_LONG).show();
return false;
}
}
private void alertUserAboutError()
{
AlertDialogFragment dialog = new AlertDialogFragment();
dialog.show(getFragmentManager(), "error_dialog");
}
}
这是CurrentWeather.java类:
package com.example.tomfinet.stormy;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
/**
* Created by tomfinet on 13/12/15.
*/
public class CurrentWeather
{
private String mIcon;
private String mSummary;
private long mTime;
private double mTemperature;
private double mHumidity;
private double mPrecipChance;
private String mTimeZone;
public String getTimeZone()
{
return mTimeZone;
}
public void setTimeZone(String timeZone)
{
mTimeZone = timeZone;
}
public String getIcon()
{
return mIcon;
}
public void setIcon(String icon)
{
mIcon = icon;
}
public int getIconId()
{
//clear-day, clear-night, rain, snow, sleet, wind, fog, cloudy, partly-cloudy-day, or partly-cloudy-night
int iconId = R.mipmap.clear_day;
if (mIcon.equals("clear-day"))
{
iconId = R.mipmap.clear_day;
} else if (mIcon.equals("clear-night"))
{
iconId = R.mipmap.clear_night;
} else if (mIcon.equals("rain"))
{
iconId = R.mipmap.rain;
} else if (mIcon.equals("snow"))
{
iconId = R.mipmap.snow;
} else if (mIcon.equals("sleet"))
{
iconId = R.mipmap.sleet;
} else if (mIcon.equals("wind"))
{
iconId = R.mipmap.wind;
} else if (mIcon.equals("fog"))
{
iconId = R.mipmap.fog;
} else if (mIcon.equals("cloudy"))
{
iconId = R.mipmap.cloudy;
} else if (mIcon.equals("partly-cloudy-day")) {
iconId = R.mipmap.partly_cloudy;
} else if (mIcon.equals("partly-cloudy-night")) {
iconId = R.mipmap.cloudy_night;
}
return iconId;
}
public String getSummary()
{
return mSummary;
}
public void setSummary(String summary)
{
mSummary = summary;
}
public long getTime()
{
return mTime;
}
public String getFormattedTime()
{
SimpleDateFormat formatter = new SimpleDateFormat("h:mm a");
formatter.setTimeZone(TimeZone.getTimeZone(getTimeZone()));
Date dateTime = new Date(getTime() * 1000);
String timeString = formatter.format(dateTime);
return timeString;
}
public void setTime(long time)
{
mTime = time;
}
public double getTemperature()
{
return (int) Math.round(mTemperature);
}
public void setTemperature(double temperature)
{
mTemperature = temperature;
}
public double getHumidity()
{
return mHumidity;
}
public void setHumidity(double humidity)
{
mHumidity = humidity;
}
public double getPrecipChance() {
double precipPercentage = mPrecipChance * 100;
return (int) Math.round(precipPercentage);
}
public void setPrecipChance(double precipChance)
{
mPrecipChance = precipChance;
}
}
这是AlertDialogFragment.java类:
package com.example.tomfinet.stormy;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
/**
* Created by tomfinet on 12/12/15.
*/
public class AlertDialogFragment extends DialogFragment
{
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
Context context = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setTitle(context.getString(R.string.error_title))
.setMessage(context.getString(R.string.error_message))
.setPositiveButton(context.getString(R.string.error_ok_button_text), null);
AlertDialog dialog = builder.create();
return dialog;
}
}
如何解决此运行时错误?
感谢您的帮助!