Загружаю png изображение через Picasso по url, вот только перед relativeLayout.setBackground
выдает исключение что я использую main поток, вызов SetBackground
идет в методе OnCreate
.
Подскажите, в чем может быть ошибка
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1 java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:299) at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) at java.util.concurrent.FutureTask.setException(FutureTask.java:124) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) at java.util.concurrent.FutureTask.run(FutureTask.java:137) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) at java.lang.Thread.run(Thread.java:856) Caused by: java.lang.IllegalStateException: Method call should happen from the main thread. at com.squareup.picasso.Utils.checkMain(Utils.java:136) at com.squareup.picasso.RequestCreator.into(RequestCreator.java:496) at com.example.user_android.otvchat.MainActivity$SetBackground.doInBackground(MainActivity.java:386) at com.example.user_android.otvchat.MainActivity$SetBackground.doInBackground(MainActivity.java:367) at android.os.AsyncTask$2.call(AsyncTask.java:287) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at java.util.concurrent.FutureTask.run(FutureTask.java:137) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) at java.lang.Thread.run(Thread.java:856)
public class MainActivity extends AppCompatActivity {
private ImageButton btn;
private TextView txtMain;
private TextView txtSecond;
private TextView txtSecond2;
private EditText editPhone;
private EditText editCode;
private Button back;
private boolean numberPhone = true;
private boolean saveNumber = false;
public static String NUMBER_PHONE = "";
public static String NUMBER_PHONE2 = "";
public static String userID;
private int code;
private int editCodePush;
private boolean rules;
SharedPreferences sPref;
String url;
final String SAVED_PHONE = "saved_phone";
RelativeLayout relativeLayout;
String URL = "****";
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (ImageButton) findViewById(R.id.imageButton3);
txtMain = (TextView) findViewById(R.id.textView5);
txtSecond = (TextView) findViewById(R.id.textView3);
txtSecond2 = (TextView) findViewById(R.id.textView4);
editPhone = (EditText) findViewById(R.id.editText);
editCode = (EditText) findViewById(R.id.editText2);
back = (Button) findViewById(R.id.button2);
back.setVisibility(View.INVISIBLE);
editCode.setVisibility(View.INVISIBLE);
txtSecond2.setVisibility(View.INVISIBLE);
txtSecond.setVisibility(View.INVISIBLE);
editPhone.addTextChangedListener(new MaskedWatcher("+38 (###) ###-##-##"));
setTitle("Авторизация");
relativeLayout = (RelativeLayout)findViewById(R.id.activity_main);
sPref = getPreferences(MODE_PRIVATE);
Picasso.with(getApplicationContext()).load("http://sms.binovery.gq/img/heart-back.png").into(new Target(){
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
relativeLayout.setBackground(new BitmapDrawable(getApplicationContext().getResources(), bitmap));
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_SHORT).show();
}
@Override
public void onBitmapFailed(final Drawable errorDrawable) {
Toast.makeText(getApplicationContext(),"Error", Toast.LENGTH_SHORT).show();
}
@Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
Toast.makeText(getApplicationContext(),"Loading...", Toast.LENGTH_SHORT).show();
}
});
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (saveNumber) {
if (editPhone.getText().toString().equals(sPref.getString(SAVED_PHONE, ""))) {
NUMBER_PHONE = editPhone.getText().toString();
new ShowDialogAsnc().execute();
SystemClock.sleep(1000);
Intent intent = new Intent(getApplicationContext(), NavigationDrawer.class);
intent.putExtra("regulations_btn", R.id.button6);
startActivity(intent);
}
} else if (true) {
new ShowDialogAsnc().execute();
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Spannable text = new SpannableString(txtSecond.getText());
text.setSpan(new UnderlineSpan(), 100, 104, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
txtSecond.setText(text);
txtSecond.setTextColor(Color.WHITE);
editPhone.setVisibility(View.INVISIBLE);
txtMain.setVisibility(View.INVISIBLE);
back.setVisibility(View.VISIBLE);
editCode.setVisibility(View.VISIBLE);
txtSecond2.setVisibility(View.VISIBLE);
txtSecond.setVisibility(View.VISIBLE);
NUMBER_PHONE = editPhone.getText().toString();
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
editCodePush = Integer.parseInt(editCode.getText().toString());
if (editCodePush == code) {
sPref = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor ed = sPref.edit();
ed.putString(SAVED_PHONE, NUMBER_PHONE.toString());
ed.commit();
if (!rules) {
Intent intent = new Intent(getApplicationContext(), NavigationDrawer.class);
intent.putExtra("regulations_btn", R.id.button6);
startActivity(intent);
} else {
Intent intent = new Intent(getApplicationContext(), Regulations.class);
startActivity(intent);
}
} else {
Toast.makeText(getApplicationContext(), "Не верно введен код", Toast.LENGTH_SHORT).show();
}
} catch (NumberFormatException e) {
Toast.makeText(getApplicationContext(), "Не верно введен код", Toast.LENGTH_SHORT).show();
}
}
});
} else {
Toast.makeText(getApplicationContext(), "Номер телефон введен не корректно", Toast.LENGTH_LONG).show();
}
}
});
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
back.setVisibility(View.INVISIBLE);
editCode.setVisibility(View.INVISIBLE);
txtSecond2.setVisibility(View.INVISIBLE);
txtSecond.setVisibility(View.INVISIBLE);
editPhone.setVisibility(View.VISIBLE);
txtMain.setVisibility(View.VISIBLE);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (true) {
new ShowDialogAsnc().execute();
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Spannable text = new SpannableString(txtSecond.getText());
text.setSpan(new UnderlineSpan(), 100, 104, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
txtSecond.setText(text);
txtSecond.setTextColor(Color.WHITE);
editPhone.setVisibility(View.INVISIBLE);
txtMain.setVisibility(View.INVISIBLE);
back.setVisibility(View.VISIBLE);
editCode.setVisibility(View.VISIBLE);
txtSecond2.setVisibility(View.VISIBLE);
txtSecond.setVisibility(View.VISIBLE);
NUMBER_PHONE = editPhone.getText().toString();
editCode.setText("");
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (numberPhone) {
Intent intent = new Intent(getApplicationContext(), Regulations.class);
startActivity(intent);
}
}
});
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
editCodePush = Integer.parseInt(editCode.getText().toString());
if (editCodePush == code) {
if (!rules) {
Intent intent = new Intent(getApplicationContext(), NavigationDrawer.class);
intent.putExtra("regulations_btn", R.id.button6);
startActivity(intent);
} else {
Intent intent = new Intent(getApplicationContext(), Regulations.class);
startActivity(intent);
}
} else {
Toast.makeText(getApplicationContext(), "Не верно введен код", Toast.LENGTH_SHORT).show();
}
} catch (NumberFormatException e) {
Toast.makeText(getApplicationContext(), "Не верно введен код", Toast.LENGTH_SHORT).show();
}
}
});
}
}
});
}
});
}
private class ShowDialogAsnc extends AsyncTask<Void, Integer, Void> {
String phone;
JSONObject jsonObjectCode;
@Override
protected void onPreExecute() {
phone = editPhone.getText().toString();
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... voids) {
try {
NUMBER_PHONE = phone;
jsonObjectCode = new JSONObject(new PostExample().PostExampleMethod("phone_number", phone));
SystemClock.sleep(1000);
code = jsonObjectCode.getInt("code");
rules = jsonObjectCode.isNull("read_rules");
userID = jsonObjectCode.getString("id");
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
вот только перед relativeLayout.setBackground выдает исключение что я использую main поток
Исключение как раз говорит об обратном:
Method call should happen from the main thread
То, что Вы создаете и запускаете SetBackground extends AsyncTask
в onCreate
(то есть из главного потока) в данном случае не значит ничего, так как метод doInBackground(...)
AsyncTask
'а выполняется уже не в в главном потоке.
При загрузке изображений с помощью Picasso нет необходимости самостоятельно создавать новый поток, так как Picasso уже сам работает асинхронно.
Методы relativeLayout.setBackground
и Toast.show()
можно вызвать только из главного потока, а Вы пытаетесь вызвать их в методе doInBackground(...)
AsyncTask
'а, о чем Вам и говорится в стек-трейсе.
Для решения проблемы просто уберите AsyncTask
и загружайте изображения прямо в методе onCreate(...)
.
UPD. Picasso хранит ссылку на инстанс Target
'а в виде weak reference, которая может быть почищена Garbage collector'ом. Эту проблему можно решить сделав ссылку на Target
сильной (strong).
Первый способ:
Добавляете
private Target mTarget;
как поле класса MainActivity
.
Далее в методе OnCreate()
создаете mTarget
:
mTarget = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
relativeLayout.setBackground(new BitmapDrawable(getApplicationContext().getResources(), bitmap));
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_SHORT).show();
}
@Override
public void onBitmapFailed(final Drawable errorDrawable) {
Toast.makeText(getApplicationContext(),"Error", Toast.LENGTH_SHORT).show();
}
@Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
Toast.makeText(getApplicationContext(),"Loading...", Toast.LENGTH_SHORT).show();
}
};
и после этого загружаете изображение:
Picasso.with(getApplicationContext()).load("http://sms.binovery.gq/img/heart-back.png").into(mTarget);
Второй способ:
Реализуете интерфейс Target
в Вашей MainActivity
:
public class MainActivity extends AppCompatActivity implements Target {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
}
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
relativeLayout.setBackground(new BitmapDrawable(getApplicationContext().getResources(), bitmap));
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_SHORT).show();
}
@Override
public void onBitmapFailed(final Drawable errorDrawable) {
Toast.makeText(getApplicationContext(),"Error", Toast.LENGTH_SHORT).show();
}
@Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
Toast.makeText(getApplicationContext(),"Loading...", Toast.LENGTH_SHORT).show();
}
...
}
А в методе onCreate(...)
загружаете изображение:
Picasso.with(getApplicationContext()).load("http://sms.binovery.gq/img/heart-back.png").into(this);
Виртуальный выделенный сервер (VDS) становится отличным выбором
Добрый день
Клиент шлет запрос на REST сервер на удаление записиИсполнение на Angular
Помогите пожалуйста разобраться с подключением к Базе данныхнужно сделать интерфейс и чтобы по нажатию кнопки программа подключалась к базе,...