Ответ 1
Убедитесь, что Не выполнять действия Настройки > Система > Параметры разработчика > > Приложения.
Мое приложение работает нормально, пока я не столкнулся с какой-то странной проблемой на конкретном устройстве. В приложении есть 2 мероприятия. После того, как я запустил ActivityB внутри ActivityA, ActivityA начнет без проблем. Однако после того, как я вернусь к ActivityA с нажатием кнопки аппаратного обеспечения или вызовом finish(); внутри closeButton в ActivityB, ActivityA перезагружается. Он снова запускает onCreate() и перезагружает все его содержимое. И я не меняю ориентацию телефона. Это странное поведение появляется только в 15 телефонах за 1.000 загрузки приложения.
Эта проблема возникает только в ОС Android Galaxy S3 4.1.2. И это тоже странно.
У вас есть идея, почему это происходит?
Когда я запускаю новую активность внутри пульта, например:
ActivityA.java (MesajlarListViewActivity)
public class MesajlarListViewActivity extends TrackedActivity {
Context context = null;
// contacts JSONArray
JSONArray contacts = null;
ArrayList<Message> productArray = new ArrayList<Message>();
private ProductAdapter adapter;
private ListView productList;
private Runnable viewOrders;
private HoloProgressIndicator profilInfoProgress = null;
ImageView kapatButton = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.mesajlar_list);
context = this;
kapatButton = (ImageView) findViewById(R.id.kapat_button);
/* kapat button onclick listener. */
// =================================================================================================================
kapatButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view)
{
// Set vibration on touch.
KnetGenericClass.vibratePhone(context);
finish();
}
});
// =================================================================================================================
//Progress bar.
profilInfoProgress = (HoloProgressIndicator) findViewById(R.id.profil_info_progress);
// cheking internet connectivity.
if(KnetGenericClass.checkInternetConnection(context))
{
// start task!
/* internet var ise web service baglantisi kurmaya baslayabiliriz. */
startActivityIndicatorWithThread();
}
else
{
KnetGenericClass.printErrorMessage(context, "Bağlantı Hatası",
"Lütfen internet bağlantınızı kontrol ediniz.");
}
productList = (ListView) findViewById(R.id.product_list);
adapter = new ProductAdapter(this, R.layout.message_row, productArray);
productList.setAdapter(adapter);
// When user click a view on list view new page is appearing.
productList.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
// Set vibration on touch.
KnetGenericClass.vibratePhone(context);
/* Navigate to message detay activity class with ilan ID. */
Intent myIntent = new Intent(view.getContext(), MesajDetayActivity.class);
myIntent.putExtra("messageID", productArray.get(position).getId());
startActivity(myIntent);
// setting image of clicked message null.
RelativeLayout relativeLayout = (RelativeLayout) view;
ImageView unreadedImageView = (ImageView) relativeLayout.findViewById(R.id.unreaded_image);
unreadedImageView.setImageResource(0);
}
});
}
public class ProductAdapter extends ArrayAdapter<Message> {
ArrayList<Message> items;
public ProductAdapter(Context context, int textViewResourceId, ArrayList<Message> objects) {
super(context, textViewResourceId, objects);
this.items = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
if(convertView == null)
{
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.message_row, null);
}
ImageView unreadedImageView = (ImageView) convertView.findViewById(R.id.unreaded_image);
TextView productName = (TextView) convertView.findViewById(R.id.product_name);
TextView productDetail = (TextView) convertView.findViewById(R.id.product_detail);
// TextView productDate = (TextView)
// convertView.findViewById(R.id.product_date);
TextView sentDate = (TextView) convertView.findViewById(R.id.product_date);
productName.setText(items.get(position).getSender());
productDetail.setText(items.get(position).getTitle());
// String bodyNoHTML = items.get(position).getBody();
if(items.get(position).getIsReaded())
{
unreadedImageView.setImageResource(0);
}
else
{
unreadedImageView.setImageResource(R.drawable.bluedot);
}
String dateStr = items.get(position).getSentDate();
try
{
sentDate.setText(dateStr.substring(6, 8) + "." + dateStr.substring(4, 6) + "." + dateStr.substring(0, 4)
+" "+dateStr.substring(8, 10)+":"+dateStr.substring(10, 12));
}
catch(Exception e)
{
sentDate.setText("");
}
return convertView;
}
}// @end of product adapter class.
/* web service'e baglanti kurulan methodu threadin icerisinde cagiriyoruz. */
public void startActivityIndicatorWithThread()
{
// ==============================================================================================
// getting ilan details into arraylist.
// setting up thread.
viewOrders = new Runnable() {
public void run()
{
getMessageListFromWebService();
}
};
Thread thread = new Thread(null, viewOrders, "MagentoBackground");
thread.start();
profilInfoProgress.start();
// ==============================================================================================
// @end of the thread declaration.
}
public void getMessageListFromWebService()
{
// Creating JSON Parser instance
JSONParser jParser = new JSONParser(context);
// getting JSON string from URL
JSONArray jsonArray = jParser.getAuthorizedInfoFromUrlToJSONArray(
WebServiceInfo.getKnetWebServiceLink()+"/API/Member/GetInboxMessageList", MainActivity.getAccessToken());
// if json is null then there is a problem.
if(jsonArray == null)
{
// if json array is null then print error message.
runOnUiThread(showAlertMessage);
runOnUiThread(returnRes);
return;
}
try
{
// Eger aranilan kritere gore ilan yok ise hata mesaji basiyoruz.
if(jsonArray.length() == 0)
{
// if json array is null then print error message.
runOnUiThread(showAlertIlanYokMessage);
runOnUiThread(returnRes);
return;
}
// looping through All Contacts
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject c = jsonArray.getJSONObject(i);
// Storing each json item in variable
// String id = c.getString(TAG_ID);
String id = c.getString("Id");
String sender = c.getString("Sender");
// String body = c.getString("Body");
String title = c.getString("Title");
String sentDate = c.getString("SentDate");
Boolean isReaded = c.getBoolean("IsRead");
Message productObject = new Message(id, sender, "", title, sentDate, isReaded);
productArray.add(productObject);
}
}
catch (Exception e)
{
Log.e("BACKGROUND_PROC", e.getMessage());
}
runOnUiThread(returnRes);
}
// @end of thread.
private Runnable returnRes = new Runnable() {
public void run()
{
profilInfoProgress.stop();
adapter.notifyDataSetChanged();// refreshing data over adapter in
// list view.
}
};
// @end of thread.
private Runnable showAlertMessage = new Runnable() {
public void run()
{
// Bu hata genelde linkteki problemden, servera ulasilamamasindan
// veya timeouttan meydana gelir.
Toast.makeText(getApplicationContext(),
"Mesajlar alınamadı lütfen daha sonra tekrar deneyiniz.",
Toast.LENGTH_LONG).show();
}
};
private Runnable showAlertIlanYokMessage = new Runnable() {
public void run()
{
// Bu hata aranilan kelimeye gore ilan bulunamazsa gelir.
Toast.makeText(getApplicationContext(),
"Mesajlar bulunamadı.",
Toast.LENGTH_LONG).show();
}
};
}
=============================================== =========================
ActivityB.java (MesajDetayActivity.java)
public class MesajDetayActivity extends TrackedActivity {
private HoloProgressIndicator profilInfoProgress = null;
TextView titleTextView = null;
TextView senderTextView = null;
TextView dateTextView = null;
WebView bodyWebView = null;
Message messageObject = null;
String messageID = null;
ImageView kapatButton = null;
Context context;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.mesajdetaylari);
context = this;
kapatButton = (ImageView) findViewById(R.id.kapat_button);
/* kapat button onclick listener. */
// =================================================================================================================
kapatButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view)
{
// Set vibration on touch.
KnetGenericClass.vibratePhone(context);
finish();
}
});
// =================================================================================================================
//Progress bar.
profilInfoProgress = (HoloProgressIndicator) findViewById(R.id.profil_info_progress);
Bundle extras = getIntent().getExtras();
if(extras != null)
{
messageID = extras.getString("messageID");
}
titleTextView = (TextView) findViewById(R.id.title_textview);
senderTextView = (TextView) findViewById(R.id.sender_textview);
dateTextView = (TextView) findViewById(R.id.date_textview);
bodyWebView = (WebView) findViewById(R.id.mesaj_webView);
// Show the ProgressDialog on this thread
profilInfoProgress.start();
// Start a new thread that will download all the data
new MakeItTask().execute();
}
// Async task.
private class MakeItTask extends AsyncTask<String, Void, Object> {
protected Object doInBackground(String... args)
{
Log.i("MyApp", "Background thread starting");
// This is where you would do all the work of downloading your data
// getting message detay
/* connect to web service */
getMessageDetayFromWebService();
return null;
}
protected void onPostExecute(Object result)
{
// Pass the result data back to the main activity
// TakipListeActivity.this.data = result;
try
{
titleTextView.setText("Başlık: " + messageObject.getTitle());
senderTextView.setText("Gönderen: " + messageObject.getSender());
dateTextView.setText("Tarih: " + messageObject.getSentDate().substring(6, 8) + "."
+ messageObject.getSentDate().substring(4, 6) + "."
+ messageObject.getSentDate().substring(0, 4));
if(!messageObject.getBody().contains("img"))
{
bodyWebView.loadDataWithBaseURL(null, messageObject.getBody(), "text/html", "UTF-8", null);
}
}
catch (Exception e)
{
Log.e(CONNECTIVITY_SERVICE, "Mesaj Detayi bilgileri basilamadi.");
}
profilInfoProgress.stop();
}
}
/* web service'e baglanti kurulan methodu threadin icerisinde cagiriyoruz. */
public void getMessageDetayFromWebService()
{
// Creating JSON Parser instance
JSONParser jParser = new JSONParser(context);
// getting JSON string from URL
JSONObject jsonObject = jParser.getAuthorizedInfoFromUrlToJSONObject(
WebServiceInfo.getKnetWebServiceLink()+"/API/Member/GetInboxMessage/" + messageID, MainActivity.getAccessToken());
// if json is null then there is a problem.
if(jsonObject == null)
{
return;
}
try
{
String title = jsonObject.getString("Title");
String id = jsonObject.getString("Id");
String sender = jsonObject.getString("Sender");
String date = jsonObject.getString("SentDate");
String body = jsonObject.getString("Body");
messageObject = new Message(id, sender, body, title, date, true);
}
catch (Exception e)
{
Log.e("BACKGROUND_PROC", e.getMessage());
}
}// @end of getIlanDetayFromWebService.
}
Изменить: не только эти два действия имеют эту проблему, но и все действия, действующие на некоторых телефонах.
Убедитесь, что Не выполнять действия Настройки > Система > Параметры разработчика > > Приложения.
Документация по действиям (http://developer.android.com/reference/android/app/Activity.html) рассказывает о жизненном цикле фоновой активности:
Фоновая активность (активность, которая не видна пользователю и приостановлена) больше не критична, поэтому система может безопасно убить свой процесс для восстановления памяти для других передних или видимых процессов. Если его процесс должен быть убит, когда пользователь перейдет к действию (сделав его видимым на экране снова), его метод onCreate (Bundle) будет вызван с сохраненнымInstanceState, который он ранее поставил в onSaveInstanceState (Bundle), чтобы он может перезапустить себя в том же состоянии, в котором пользователь оставил его.
Другими словами, ActivityA может или не может быть уничтожен операционной системой, в то время как ActivityB активен, поэтому эту ситуацию нужно обрабатывать в коде. Если ActivityA будет уничтожен, будет вызываться onCreate (Bundle), когда пользователь нажимает кнопку "Назад" в ActivityB.
Вы пытались изменить launchmode
в манифесте Android? Попытайтесь добавить это в свою декларацию активности:
android:launchMode="singleTask"
Затем попробуйте использовать startActivityForResult
вместо startActivity
. Это заставит Activity A вызвать свой метод onActivityResult(int, int, Intent)
, когда закончится Activity B, - который может пропустить этот (багги) вызов onCreate
. Затем в Activity A реализуем метод для выполнения чего-либо (например, для печати инструкции отладки):
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
Log.i("Test", "Did this work???");
//TODO send notification to your server to verify this works?
}
Там есть установка Android-разработчика под названием "Не выполнять действия". Описание этого параметра: "Уничтожьте каждое действие, как только пользователь его покинет". Это похоже на хорошее описание того, что вы видите, и поскольку вы видите его только на нескольких телефонах, идея о том, что это вызвано нестандартной настройкой системы, кажется правдоподобной.
В идеале ваше приложение будет работать в этом сценарии, даже если оно будет менее оптимальным. Но если этот параметр является проблемой для вашего приложения, вы можете документировать эту проблему для своих пользователей.
Я не вижу никаких проблем в этом поведении.
Если вы хотите сохранить состояние ActivityA
, используйте методы onSaveInstanceState
и onRestoreInstanceState
. Дополнительную информацию см. В разделе "Жизненный цикл деятельности" http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle.
См. также fooobar.com/questions/350398/... для более глубокого понимания.
Вы можете попробовать одну вещь, обеспечивающую ваш макет в onCreate()
, и выполните оставшуюся часть работы в onStart()
? если он работает?
LIKE:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show);
}
и
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.i(TAG, "On Start .....");
}
Возможно, вы должны использовать
Intent startIntent = new Intent(view.getContext(), ActivityB.class);
startActivity(startIntent);
finish() ;
и
Intent startIntent = new Intent(view.getContext(), ActivityA.class);
startActivity(startIntent);
finish() ;
каждый раз, когда вы возвращаетесь или вперед.
Он тоже столкнулся с точной проблемой и решил проблему, используя android:launchMode="standard"
в activity
of manifest
.
Переопределите onStart() и метод onResume в Activity A и проверьте, сохраняется ли проблема. и, если возможно, предоставьте здесь свой код активации A и B.
Действие A использует макет R.layout.mesajlar_list
Активность B использует макет R.layout.mesajdetaylari
Но обе имеют следующую строку кода:
kapatButton = (ImageView) findViewById(R.id.kapat_button);
В каком макете находится файл R.id.kapat_button? Использование одного и того же идентификатора в разных макетах - очень рискованная вещь. Я не могу гарантировать, что это приведет к тому, что вы видите, но это то, что может вызвать странное поведение.
Я думаю, что это не из-за ограничения памяти.
https://www.box.com/s/7pd0as03bb8wwumuc9l9
Вы должны проверить эти два действия и проверить, происходит ли это в этом примере или нет. Поделитесь своим содержимым файлов AndroidManifest.xml, это поможет с отладкой.
Недавно я получил эту проблему, и это меня раздражало. Я думаю, что проблема вокруг 2 вариантов решения проверить, но бесполезно.
О настройке "Не продолжать действия" исправлено здесь, я использовал этот код, чтобы проверить, что он опционально проверен или нет (мое тестовое устройство настраивает базу на версии 2.3.5 и не показывает эту опцию):
private boolean isAlwaysFinishActivitiesOptionEnabled() {
int alwaysFinishActivitiesInt = 0;
if (Build.VERSION.SDK_INT >= 17) {
alwaysFinishActivitiesInt = Settings.System.getInt(getApplicationContext().getContentResolver(), Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0);
} else {
alwaysFinishActivitiesInt = Settings.System.getInt(getApplicationContext().getContentResolver(), Settings.System.ALWAYS_FINISH_ACTIVITIES, 0);
}
if (alwaysFinishActivitiesInt == 1) {
return true;
} else {
return false;
}
}
Проверка результата в моем случае неверна. Я также проверяю память при запуске приложения, и ничего не происходит.
вы можете использовать android:launchMode="singleTop"
в манифесте.
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>