You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决跳转至ListActivity时的界面跳动问题?

问题描述

我有多个Activity,其他Activity的转场动画都很流畅,但每次导航到下面这个ListActivity时,界面都会出现跳动现象。我已经重写了动画类,但跳动问题依然存在。想请教下该如何解决?会不会是UI线程过载导致的?

public class ListActivity extends AppCompatActivity implements RecyclerViewAdapter.OnItemClickListener { 
    RecyclerViewAdapter recyclerViewAdapter; 
    RecyclerView recyclerView; 
    private FirebaseFirestore db = FirebaseFirestore.getInstance(); 
    private CollectionReference dbRef = db.collection("Archives"); 
    Context context; 
    FloatingActionButton fab; 
    Item clickedItem; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_list); 
        overridePendingTransition(R.anim.fade_in, R.anim.fade_out); 

        recyclerView = findViewById(R.id.recyclerView); 
        fab = findViewById(R.id.fab); 
        Toolbar toolbar = findViewById(R.id.toolbar); 

        if (toolbar != null) { 
            setSupportActionBar(toolbar); 
            getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
            getSupportActionBar().setHomeButtonEnabled(true); 
        } 

        toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
            @Override 
            public void onClick(View v) { 
                finish(); 
                overridePendingTransition(R.anim.fade_in, R.anim.fade_out); 
            } 
        }); 

        fab.setOnClickListener(new View.OnClickListener() { 
            @Override 
            public void onClick(View v) { 
                Intent intent = new Intent(ListActivity.this, EnterDataActivity.class); 
                startActivity(intent); 
            } 
        }); 

        setUpAdapter(); 
    } 

    private void setUpAdapter() { 
        Query query = dbRef.orderBy("fname", Query.Direction.DESCENDING); 
        FirestoreRecyclerOptions<Item> options = new FirestoreRecyclerOptions.Builder<Item>() 
                .setQuery(query, Item.class) 
                .build(); 

        recyclerViewAdapter = new RecyclerViewAdapter(options, ListActivity.this); 
        recyclerViewAdapter.notifyDataSetChanged(); 
        recyclerView.setHasFixedSize(true); 
        recyclerView.setLayoutManager(new LinearLayoutManager(context)); 
        recyclerView.setAdapter(recyclerViewAdapter); 
        recyclerViewAdapter.setOnItemClickListener(ListActivity.this); 
    } 

    @Override 
    public void onStart() { 
        super.onStart(); 
        recyclerViewAdapter.startListening(); 
    } 

    @Override 
    public void onStop() { 
        super.onStop(); 
        recyclerViewAdapter.stopListening(); 
    } 

    @Override 
    public void onItemClick(DocumentSnapshot documentSnapshot, int position) { 
        clickedItem = documentSnapshot.toObject(Item.class); 
        clickedItem.setId((documentSnapshot.getId())); 

        Intent intent = new Intent(ListActivity.this, DetailActivity.class); 
        intent.putExtra(First_Name, clickedItem.getFname()); 
        intent.putExtra(Middle_Name, clickedItem.getMname()); 
        intent.putExtra(Sur_Name, clickedItem.getSname()); 
        intent.putExtra(Email, clickedItem.getEmail()); 
        intent.putExtra(phone, clickedItem.getPhone()); 
        intent.putExtra(city, clickedItem.getCity()); 
        intent.putExtra(parents_Name, clickedItem.getParentsName()); 
        intent.putExtra(parents_Phone, clickedItem.getParentsContact()); 
        intent.putExtra(dob, clickedItem.getDob()); 
        intent.putExtra(emergency, clickedItem.getEmergency()); 
        intent.putExtra(profile_Picture, clickedItem.getProfilePicture()); 

        overridePendingTransition(R.anim.fade_in, R.anim.fade_out); 
        startActivityForResult(intent, 45); 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { 
        super.onActivityResult(requestCode, resultCode, data); 

        if ((requestCode == 45 && resultCode == RESULT_OK && data != null)) { 
            String fname = data.getStringExtra(First_Name); 
            String mname = data.getStringExtra(Middle_Name); 
            String sname = data.getStringExtra(Sur_Name); 
            String email = data.getStringExtra(Email); 
            String Phone = data.getStringExtra(phone); 
            String City = data.getStringExtra(city); 
            String pname = data.getStringExtra(parents_Name); 
            String pphone = data.getStringExtra(parents_Phone); 
            String Dob = data.getStringExtra(dob); 
            String Emergency = data.getStringExtra(emergency); 
            String profile = data.getStringExtra(profile_Picture); 

            Item items = new Item(fname, mname, sname, email, Phone, City, pname, pphone, Dob, Emergency, profile); 

            db.collection("Archives").document(clickedItem.getId()) 
                    .set(items).addOnSuccessListener(new OnSuccessListener<Void>() { 
                @Override 
                public void onSuccess(Void aVoid) { 
                    Toast.makeText(ListActivity.this, "Updated Successfully", Toast.LENGTH_LONG).show(); 
                } 
            }); 
        } 
    } 
}
可能的原因与解决方案

我帮你梳理了代码里几个可能导致转场跳动的点,咱们逐一排查:

1. 未初始化的Context导致布局异常

你在setUpAdapter()里用了new LinearLayoutManager(context),但代码里只声明了Context context,却没给它赋值!这会让布局管理器初始化出问题,RecyclerView的布局计算混乱,直接引发转场时的跳动。

修复方法:
在onCreate里给context赋值:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_list); 
    context = this; // 加上这行,初始化context
    // ... 其他代码
}

2. 无意义的notifyDataSetChanged()调用

刚创建完recyclerViewAdapter就调用notifyDataSetChanged()完全没必要——此时Firestore还没开始加载数据,这行代码只会触发不必要的布局刷新,干扰转场动画的流畅性。

修复方法:
直接删掉这行代码:

// recyclerViewAdapter.notifyDataSetChanged(); // 移除这行无效代码

3. 转场动画的调用时机错误

你在onCreate里直接调用了overridePendingTransition,但此时Activity的布局还没完全初始化完成,动画和布局绘制冲突就会导致跳动。另外,onItemClick里把overridePendingTransition放在startActivityForResult之前也是错误的顺序。

修复方法:

  • 移除onCreate里的overridePendingTransition调用,转场动画更合理的设置时机是在启动当前Activity的前一个页面中,或者在当前Activity的onResume之后处理。
  • 调整onItemClick里的代码顺序:
startActivityForResult(intent, 45);
overridePendingTransition(R.anim.fade_in, R.anim.fade_out); // 移到startActivityForResult之后

4. UI线程过载的排查与优化

如果上面的修改后还有跳动,就得考虑UI线程是否被阻塞。Firestore的startListening()是后台加载数据,但数据返回后更新RecyclerView是在UI线程,如果数据量太大或者Item布局复杂,就会卡顿。

优化建议:

  • 给Firestore查询添加分页:用limit()限制单次加载的数据量,配合startAfter()实现分页加载,避免一次性渲染大量Item。
  • 优化Item布局:减少布局嵌套层级,用Android Studio的Layout Inspector检查过度绘制问题,尽量用ConstraintLayout替代嵌套的LinearLayout/RelativeLayout。
  • 保持recyclerView.setHasFixedSize(true)开启(你已经加了这行,做得很好),它能减少RecyclerView的重绘次数。

5. 转场动画本身的问题

检查你的fade_in和fade_out动画文件,确保没有多余的位移属性。比如如果动画里不小心加了translateX/translateY,就会导致界面跳动。

示例正确的淡入动画(fade_in.xml):

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromAlpha="0.0"
    android:toAlpha="1.0" />

淡出动画(fade_out.xml):

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromAlpha="1.0"
    android:toAlpha="0.0" />

按上面的步骤逐一排查,应该能解决转场跳动的问题。

内容的提问来源于stack exchange,提问作者user11318019

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:22:00